Merge "Separate animation into separate class."
diff --git a/api/current.txt b/api/current.txt
index 665b054..20b0be6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3694,6 +3694,7 @@
public static class Notification.Builder {
ctor public Notification.Builder(android.content.Context);
+ method public android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
method public android.app.Notification.Builder addKind(java.lang.String);
method public android.app.Notification getNotification();
method public android.app.Notification.Builder setAutoCancel(boolean);
@@ -7312,6 +7313,7 @@
method public static android.database.sqlite.SQLiteDatabase create(android.database.sqlite.SQLiteDatabase.CursorFactory);
method public int delete(java.lang.String, java.lang.String, java.lang.String[]);
method public static boolean deleteDatabase(java.io.File);
+ method public void disableWriteAheadLogging();
method public boolean enableWriteAheadLogging();
method public void endTransaction();
method public void execSQL(java.lang.String) throws android.database.SQLException;
@@ -25899,6 +25901,7 @@
ctor public AbsSeekBar(android.content.Context, android.util.AttributeSet);
ctor public AbsSeekBar(android.content.Context, android.util.AttributeSet, int);
method public int getKeyProgressIncrement();
+ method public android.graphics.drawable.Drawable getThumb();
method public int getThumbOffset();
method public void setKeyProgressIncrement(int);
method public void setThumb(android.graphics.drawable.Drawable);
@@ -26621,8 +26624,14 @@
ctor public GridView(android.content.Context, android.util.AttributeSet);
ctor public GridView(android.content.Context, android.util.AttributeSet, int);
method public android.widget.ListAdapter getAdapter();
+ method public int getColumnWidth();
+ method public int getGravity();
+ method public int getHorizontalSpacing();
method public int getNumColumns();
+ method public int getRequestedColumnWidth();
+ method public int getRequestedHorizontalSpacing();
method public int getStretchMode();
+ method public int getVerticalSpacing();
method public void setColumnWidth(int);
method public void setGravity(int);
method public void setHorizontalSpacing(int);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index c15c49f..53a0186 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -62,6 +62,7 @@
private boolean mStopOption = false;
private int mRepeat = 0;
+ private int mUserId = 0;
private String mProfileFile;
@@ -135,7 +136,7 @@
runToUri(false);
} else if (op.equals("to-intent-uri")) {
runToUri(true);
- } else if (op.equals("switch-profile")) {
+ } else if (op.equals("switch-user")) {
runSwitchUser();
} else {
throw new IllegalArgumentException("Unknown command: " + op);
@@ -152,6 +153,7 @@
mStopOption = false;
mRepeat = 0;
mProfileFile = null;
+ mUserId = 0;
Uri data = null;
String type = null;
@@ -308,6 +310,8 @@
mStopOption = true;
} else if (opt.equals("--opengl-trace")) {
mStartFlags |= ActivityManager.START_FLAG_OPENGL_TRACES;
+ } else if (opt.equals("--user")) {
+ mUserId = Integer.parseInt(nextArgRequired());
} else {
System.err.println("Error: Unknown option: " + opt);
showUsage();
@@ -407,7 +411,8 @@
System.err.println("Error: Package manager not running; aborting");
return;
}
- List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0);
+ List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0,
+ mUserId);
if (activities == null || activities.size() <= 0) {
System.err.println("Error: Intent does not match any activities: "
+ intent);
@@ -550,7 +555,7 @@
IntentReceiver receiver = new IntentReceiver();
System.out.println("Broadcasting: " + intent);
mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, null, true, false,
- Binder.getOrigCallingUser());
+ mUserId);
receiver.waitForFinish();
}
@@ -1294,6 +1299,7 @@
" am display-size [reset|MxN]\n" +
" am to-uri [INTENT]\n" +
" am to-intent-uri [INTENT]\n" +
+ " am switch-user <USER_ID>\n" +
"\n" +
"am start: start an Activity. Options are:\n" +
" -D: enable debugging\n" +
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index ac5bffe..4d638d0 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -146,18 +146,18 @@
return;
}
- if ("create-profile".equals(op)) {
- runCreateProfile();
+ if ("create-user".equals(op)) {
+ runCreateUser();
return;
}
- if ("remove-profile".equals(op)) {
- runRemoveProfile();
+ if ("remove-user".equals(op)) {
+ runRemoveUser();
return;
}
- if ("list-profiles".equals(op)) {
- runListProfiles();
+ if ("list-users".equals(op)) {
+ runListUsers();
return;
}
@@ -215,6 +215,8 @@
runListLibraries();
} else if ("instrumentation".equals(type)) {
runListInstrumentation();
+ } else if ("users".equals(type)) {
+ runListUsers();
} else {
System.err.println("Error: unknown list type '" + type + "'");
showUsage();
@@ -832,10 +834,10 @@
}
}
- public void runCreateProfile() {
+ public void runCreateUser() {
// Need to be run as root
if (Process.myUid() != ROOT_UID) {
- System.err.println("Error: create-profile must be run as root");
+ System.err.println("Error: create-user must be run as root");
return;
}
String name;
@@ -848,7 +850,7 @@
name = arg;
try {
if (mPm.createUser(name, 0) == null) {
- System.err.println("Error: couldn't create profile.");
+ System.err.println("Error: couldn't create User.");
showUsage();
}
} catch (RemoteException e) {
@@ -858,10 +860,10 @@
}
- public void runRemoveProfile() {
+ public void runRemoveUser() {
// Need to be run as root
if (Process.myUid() != ROOT_UID) {
- System.err.println("Error: remove-profile must be run as root");
+ System.err.println("Error: remove-user must be run as root");
return;
}
int userId;
@@ -880,7 +882,7 @@
}
try {
if (!mPm.removeUser(userId)) {
- System.err.println("Error: couldn't remove profile.");
+ System.err.println("Error: couldn't remove user.");
showUsage();
}
} catch (RemoteException e) {
@@ -889,10 +891,10 @@
}
}
- public void runListProfiles() {
+ public void runListUsers() {
// Need to be run as root
if (Process.myUid() != ROOT_UID) {
- System.err.println("Error: list-profiles must be run as root");
+ System.err.println("Error: list-users must be run as root");
return;
}
try {
@@ -1029,7 +1031,29 @@
return "unknown";
}
+ private boolean isNumber(String s) {
+ try {
+ Integer.parseInt(s);
+ } catch (NumberFormatException nfe) {
+ return false;
+ }
+ return true;
+ }
+
private void runSetEnabledSetting(int state) {
+ int userId = 0;
+ String option = nextOption();
+ if (option != null && option.equals("--user")) {
+ String optionData = nextOptionData();
+ if (optionData == null || !isNumber(optionData)) {
+ System.err.println("Error: no USER_ID specified");
+ showUsage();
+ return;
+ } else {
+ userId = Integer.parseInt(optionData);
+ }
+ }
+
String pkg = nextArg();
if (pkg == null) {
System.err.println("Error: no package or component specified");
@@ -1039,20 +1063,20 @@
ComponentName cn = ComponentName.unflattenFromString(pkg);
if (cn == null) {
try {
- mPm.setApplicationEnabledSetting(pkg, state, 0);
+ mPm.setApplicationEnabledSetting(pkg, state, 0, userId);
System.err.println("Package " + pkg + " new state: "
+ enabledSettingToString(
- mPm.getApplicationEnabledSetting(pkg)));
+ mPm.getApplicationEnabledSetting(pkg, userId)));
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
}
} else {
try {
- mPm.setComponentEnabledSetting(cn, state, 0);
+ mPm.setComponentEnabledSetting(cn, state, 0, userId);
System.err.println("Component " + cn.toShortString() + " new state: "
+ enabledSettingToString(
- mPm.getComponentEnabledSetting(cn)));
+ mPm.getComponentEnabledSetting(cn, userId)));
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
@@ -1096,7 +1120,7 @@
*/
private void displayPackageFilePath(String pckg) {
try {
- PackageInfo info = mPm.getPackageInfo(pckg, 0);
+ PackageInfo info = mPm.getPackageInfo(pckg, 0, 0);
if (info != null && info.applicationInfo != null) {
System.out.print("package:");
System.out.println(info.applicationInfo.sourceDir);
@@ -1112,7 +1136,7 @@
if (res != null) return res;
try {
- ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0);
+ ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0, 0);
AssetManager am = new AssetManager();
am.addAssetPath(ai.publicSourceDir);
res = new Resources(am, null, null);
@@ -1178,19 +1202,20 @@
System.err.println(" pm list instrumentation [-f] [TARGET-PACKAGE]");
System.err.println(" pm list features");
System.err.println(" pm list libraries");
+ System.err.println(" pm list users");
System.err.println(" pm path PACKAGE");
System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH");
System.err.println(" pm uninstall [-k] PACKAGE");
System.err.println(" pm clear PACKAGE");
- System.err.println(" pm enable PACKAGE_OR_COMPONENT");
- System.err.println(" pm disable PACKAGE_OR_COMPONENT");
- System.err.println(" pm disable-user PACKAGE_OR_COMPONENT");
+ System.err.println(" pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
+ System.err.println(" pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
+ System.err.println(" pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
System.err.println(" pm grant PACKAGE PERMISSION");
System.err.println(" pm revoke PACKAGE PERMISSION");
System.err.println(" pm set-install-location [0/auto] [1/internal] [2/external]");
System.err.println(" pm get-install-location");
- System.err.println(" pm create-profile USER_NAME");
- System.err.println(" pm remove-profile USER_ID");
+ System.err.println(" pm create-user USER_NAME");
+ System.err.println(" pm remove-user USER_ID");
System.err.println("");
System.err.println("pm list packages: prints all packages, optionally only");
System.err.println(" those whose package name contains the text in FILTER. Options:");
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index e47cdc0..64df5d1 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -176,8 +176,9 @@
}
onDrainThisBuffer(msg);
- } else if (what == ACodec::kWhatEOS) {
- printf("$\n");
+ } else if (what == ACodec::kWhatEOS
+ || what == ACodec::kWhatError) {
+ printf((what == ACodec::kWhatEOS) ? "$\n" : "E\n");
int64_t delayUs = ALooper::GetNowUs() - mStartTimeUs;
@@ -412,7 +413,8 @@
sp<AMessage> reply;
CHECK(msg->findMessage("reply", &reply));
- if (mSeekState == SEEK_FLUSHING) {
+ if (mSource == NULL || mSeekState == SEEK_FLUSHING) {
+ reply->setInt32("err", ERROR_END_OF_STREAM);
reply->post();
return;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2a3e213..0860890 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1586,7 +1586,7 @@
ApplicationInfo ai = null;
try {
ai = getPackageManager().getApplicationInfo(packageName,
- PackageManager.GET_SHARED_LIBRARY_FILES);
+ PackageManager.GET_SHARED_LIBRARY_FILES, UserId.myUserId());
} catch (RemoteException e) {
// Ignore
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 758ce09..f38540c 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -49,6 +49,7 @@
import android.net.Uri;
import android.os.Process;
import android.os.RemoteException;
+import android.os.UserId;
import android.util.Log;
import java.lang.ref.WeakReference;
@@ -67,7 +68,7 @@
public PackageInfo getPackageInfo(String packageName, int flags)
throws NameNotFoundException {
try {
- PackageInfo pi = mPM.getPackageInfo(packageName, flags);
+ PackageInfo pi = mPM.getPackageInfo(packageName, flags, UserId.myUserId());
if (pi != null) {
return pi;
}
@@ -197,7 +198,7 @@
public ApplicationInfo getApplicationInfo(String packageName, int flags)
throws NameNotFoundException {
try {
- ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags);
+ ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags, UserId.myUserId());
if (ai != null) {
return ai;
}
@@ -212,7 +213,7 @@
public ActivityInfo getActivityInfo(ComponentName className, int flags)
throws NameNotFoundException {
try {
- ActivityInfo ai = mPM.getActivityInfo(className, flags);
+ ActivityInfo ai = mPM.getActivityInfo(className, flags, UserId.myUserId());
if (ai != null) {
return ai;
}
@@ -227,7 +228,7 @@
public ActivityInfo getReceiverInfo(ComponentName className, int flags)
throws NameNotFoundException {
try {
- ActivityInfo ai = mPM.getReceiverInfo(className, flags);
+ ActivityInfo ai = mPM.getReceiverInfo(className, flags, UserId.myUserId());
if (ai != null) {
return ai;
}
@@ -242,7 +243,7 @@
public ServiceInfo getServiceInfo(ComponentName className, int flags)
throws NameNotFoundException {
try {
- ServiceInfo si = mPM.getServiceInfo(className, flags);
+ ServiceInfo si = mPM.getServiceInfo(className, flags, UserId.myUserId());
if (si != null) {
return si;
}
@@ -257,7 +258,7 @@
public ProviderInfo getProviderInfo(ComponentName className, int flags)
throws NameNotFoundException {
try {
- ProviderInfo pi = mPM.getProviderInfo(className, flags);
+ ProviderInfo pi = mPM.getProviderInfo(className, flags, UserId.myUserId());
if (pi != null) {
return pi;
}
@@ -422,6 +423,7 @@
@SuppressWarnings("unchecked")
@Override
public List<ApplicationInfo> getInstalledApplications(int flags) {
+ int userId = UserId.getUserId(Process.myUid());
try {
final List<ApplicationInfo> applicationInfos = new ArrayList<ApplicationInfo>();
ApplicationInfo lastItem = null;
@@ -429,7 +431,7 @@
do {
final String lastKey = lastItem != null ? lastItem.packageName : null;
- slice = mPM.getInstalledApplications(flags, lastKey);
+ slice = mPM.getInstalledApplications(flags, lastKey, userId);
lastItem = slice.populateList(applicationInfos, ApplicationInfo.CREATOR);
} while (!slice.isLastSlice());
@@ -445,7 +447,7 @@
return mPM.resolveIntent(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags);
+ flags, UserId.myUserId());
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
@@ -458,7 +460,8 @@
return mPM.queryIntentActivities(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags);
+ flags,
+ UserId.myUserId());
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
@@ -490,7 +493,7 @@
try {
return mPM.queryIntentActivityOptions(caller, specifics,
specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
- flags);
+ flags, UserId.myUserId());
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
@@ -502,7 +505,8 @@
return mPM.queryIntentReceivers(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags);
+ flags,
+ UserId.myUserId());
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
@@ -514,7 +518,8 @@
return mPM.resolveService(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags);
+ flags,
+ UserId.myUserId());
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
@@ -526,7 +531,8 @@
return mPM.queryIntentServices(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags);
+ flags,
+ UserId.myUserId());
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
@@ -536,7 +542,7 @@
public ProviderInfo resolveContentProvider(String name,
int flags) {
try {
- return mPM.resolveContentProvider(name, flags);
+ return mPM.resolveContentProvider(name, flags, UserId.myUserId());
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
@@ -1026,7 +1032,7 @@
public void clearApplicationUserData(String packageName,
IPackageDataObserver observer) {
try {
- mPM.clearApplicationUserData(packageName, observer);
+ mPM.clearApplicationUserData(packageName, observer, UserId.myUserId());
} catch (RemoteException e) {
// Should never happen!
}
@@ -1139,7 +1145,7 @@
public void setComponentEnabledSetting(ComponentName componentName,
int newState, int flags) {
try {
- mPM.setComponentEnabledSetting(componentName, newState, flags);
+ mPM.setComponentEnabledSetting(componentName, newState, flags, UserId.myUserId());
} catch (RemoteException e) {
// Should never happen!
}
@@ -1148,7 +1154,7 @@
@Override
public int getComponentEnabledSetting(ComponentName componentName) {
try {
- return mPM.getComponentEnabledSetting(componentName);
+ return mPM.getComponentEnabledSetting(componentName, UserId.myUserId());
} catch (RemoteException e) {
// Should never happen!
}
@@ -1159,7 +1165,7 @@
public void setApplicationEnabledSetting(String packageName,
int newState, int flags) {
try {
- mPM.setApplicationEnabledSetting(packageName, newState, flags);
+ mPM.setApplicationEnabledSetting(packageName, newState, flags, UserId.myUserId());
} catch (RemoteException e) {
// Should never happen!
}
@@ -1168,7 +1174,7 @@
@Override
public int getApplicationEnabledSetting(String packageName) {
try {
- return mPM.getApplicationEnabledSetting(packageName);
+ return mPM.getApplicationEnabledSetting(packageName, UserId.myUserId());
} catch (RemoteException e) {
// Should never happen!
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index de9470e..5340fbb 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -194,7 +194,7 @@
ApplicationInfo ai = null;
try {
ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
- PackageManager.GET_SHARED_LIBRARY_FILES);
+ PackageManager.GET_SHARED_LIBRARY_FILES, UserId.myUserId());
} catch (RemoteException e) {
throw new AssertionError(e);
}
@@ -351,7 +351,7 @@
IPackageManager pm = ActivityThread.getPackageManager();
android.content.pm.PackageInfo pi;
try {
- pi = pm.getPackageInfo(mPackageName, 0);
+ pi = pm.getPackageInfo(mPackageName, 0, UserId.myUserId());
} catch (RemoteException e) {
throw new AssertionError(e);
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 5325af0..04ab407 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -23,9 +23,11 @@
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import android.util.IntProperty;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.RemoteViews;
@@ -185,6 +187,13 @@
*/
public RemoteViews contentView;
+
+ /**
+ * The view that will represent this notification in the pop-up "intruder alert" dialog.
+ * @hide
+ */
+ public RemoteViews intruderView;
+
/**
* The bitmap that may escape the bounds of the panel and bar.
*/
@@ -418,6 +427,64 @@
private Bundle extras;
/**
+ * Structure to encapsulate an "action", including title and icon, that can be attached to a Notification.
+ * @hide
+ */
+ private static class Action implements Parcelable {
+ public int icon;
+ public CharSequence title;
+ public PendingIntent actionIntent;
+ @SuppressWarnings("unused")
+ public Action() { }
+ private Action(Parcel in) {
+ icon = in.readInt();
+ title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ if (in.readInt() == 1) {
+ actionIntent = PendingIntent.CREATOR.createFromParcel(in);
+ }
+ }
+ public Action(int icon_, CharSequence title_, PendingIntent intent_) {
+ this.icon = icon_;
+ this.title = title_;
+ this.actionIntent = intent_;
+ }
+ @Override
+ public Action clone() {
+ return new Action(
+ this.icon,
+ this.title.toString(),
+ this.actionIntent // safe to alias
+ );
+ }
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(icon);
+ TextUtils.writeToParcel(title, out, flags);
+ if (actionIntent != null) {
+ out.writeInt(1);
+ actionIntent.writeToParcel(out, flags);
+ } else {
+ out.writeInt(0);
+ }
+ }
+ public static final Parcelable.Creator<Action> CREATOR
+ = new Parcelable.Creator<Action>() {
+ public Action createFromParcel(Parcel in) {
+ return new Action(in);
+ }
+ public Action[] newArray(int size) {
+ return new Action[size];
+ }
+ };
+ }
+
+ private Action[] actions;
+
+ /**
* Constructs a Notification object with default values.
* You might want to consider using {@link Builder} instead.
*/
@@ -506,12 +573,17 @@
}
priority = parcel.readInt();
-
+
kind = parcel.createStringArray(); // may set kind to null
if (parcel.readInt() != 0) {
extras = parcel.readBundle();
}
+
+ actions = parcel.createTypedArray(Action.CREATOR);
+ if (parcel.readInt() != 0) {
+ intruderView = RemoteViews.CREATOR.createFromParcel(parcel);
+ }
}
@Override
@@ -571,6 +643,14 @@
}
+ that.actions = new Action[this.actions.length];
+ for(int i=0; i<this.actions.length; i++) {
+ that.actions[i] = this.actions[i].clone();
+ }
+ if (this.intruderView != null) {
+ that.intruderView = this.intruderView.clone();
+ }
+
return that;
}
@@ -658,6 +738,15 @@
} else {
parcel.writeInt(0);
}
+
+ parcel.writeTypedArray(actions, 0);
+
+ if (intruderView != null) {
+ parcel.writeInt(1);
+ intruderView.writeToParcel(parcel, 0);
+ } else {
+ parcel.writeInt(0);
+ }
}
/**
@@ -769,7 +858,14 @@
sb.append(this.kind[i]);
}
}
- sb.append("])");
+ sb.append("]");
+ if (actions != null) {
+ sb.append(" ");
+ sb.append(actions.length);
+ sb.append(" action");
+ if (actions.length > 1) sb.append("s");
+ }
+ sb.append(")");
return sb.toString();
}
@@ -821,6 +917,7 @@
private ArrayList<String> mKindList = new ArrayList<String>(1);
private Bundle mExtras;
private int mPriority;
+ private ArrayList<Action> mActions = new ArrayList<Action>(3);
/**
* Constructs a new Builder with the defaults:
@@ -1203,6 +1300,19 @@
return this;
}
+ /**
+ * Add an action to this notification. Actions are typically displayed by
+ * the system as a button adjacent to the notification content.
+ *
+ * @param icon Resource ID of a drawable that represents the action.
+ * @param title Text describing the action.
+ * @param intent PendingIntent to be fired when the action is invoked.
+ */
+ public Builder addAction(int icon, CharSequence title, PendingIntent intent) {
+ mActions.add(new Action(icon, title, intent));
+ return this;
+ }
+
private void setFlag(int mask, boolean value) {
if (value) {
mFlags |= mask;
@@ -1284,6 +1394,44 @@
}
}
+ private RemoteViews makeIntruderView() {
+ RemoteViews intruderView = new RemoteViews(mContext.getPackageName(),
+ R.layout.notification_intruder_content);
+ if (mLargeIcon != null) {
+ intruderView.setImageViewBitmap(R.id.icon, mLargeIcon);
+ intruderView.setViewVisibility(R.id.icon, View.VISIBLE);
+ } else if (mSmallIcon != 0) {
+ intruderView.setImageViewResource(R.id.icon, mSmallIcon);
+ intruderView.setViewVisibility(R.id.icon, View.VISIBLE);
+ } else {
+ intruderView.setViewVisibility(R.id.icon, View.GONE);
+ }
+ if (mContentTitle != null) {
+ intruderView.setTextViewText(R.id.title, mContentTitle);
+ }
+ if (mContentText != null) {
+ intruderView.setTextViewText(R.id.text, mContentText);
+ }
+ if (mActions.size() > 0) {
+ intruderView.setViewVisibility(R.id.actions, View.VISIBLE);
+ int N = mActions.size();
+ if (N>3) N=3;
+ final int[] BUTTONS = { R.id.action0, R.id.action1, R.id.action2 };
+ for (int i=0; i<N; i++) {
+ final Action action = mActions.get(i);
+ final int buttonId = BUTTONS[i];
+
+ intruderView.setViewVisibility(buttonId, View.VISIBLE);
+ intruderView.setImageViewResource(buttonId, action.icon);
+ intruderView.setContentDescription(buttonId, action.title);
+ intruderView.setOnClickPendingIntent(buttonId, action.actionIntent);
+ }
+ } else {
+ intruderView.setViewVisibility(R.id.actions, View.GONE);
+ }
+ return intruderView;
+ }
+
/**
* Combine all of the options that have been set and return a new {@link Notification}
* object.
@@ -1309,6 +1457,7 @@
n.ledOffMS = mLedOffMs;
n.defaults = mDefaults;
n.flags = mFlags;
+ n.intruderView = makeIntruderView();
if (mLedOnMs != 0 && mLedOffMs != 0) {
n.flags |= FLAG_SHOW_LIGHTS;
}
@@ -1323,6 +1472,10 @@
}
n.priority = mPriority;
n.extras = mExtras != null ? new Bundle(mExtras) : null;
+ if (mActions.size() > 0) {
+ n.actions = new Action[mActions.size()];
+ mActions.toArray(n.actions);
+ }
return n;
}
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 9bd1940..d89d2de 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -49,8 +49,8 @@
* {@hide}
*/
interface IPackageManager {
- PackageInfo getPackageInfo(String packageName, int flags);
- int getPackageUid(String packageName);
+ PackageInfo getPackageInfo(String packageName, int flags, int userId);
+ int getPackageUid(String packageName, int userId);
int[] getPackageGids(String packageName);
String[] currentToCanonicalPackageNames(in String[] names);
@@ -64,15 +64,15 @@
List<PermissionGroupInfo> getAllPermissionGroups(int flags);
- ApplicationInfo getApplicationInfo(String packageName, int flags);
+ ApplicationInfo getApplicationInfo(String packageName, int flags ,int userId);
- ActivityInfo getActivityInfo(in ComponentName className, int flags);
+ ActivityInfo getActivityInfo(in ComponentName className, int flags, int userId);
- ActivityInfo getReceiverInfo(in ComponentName className, int flags);
+ ActivityInfo getReceiverInfo(in ComponentName className, int flags, int userId);
- ServiceInfo getServiceInfo(in ComponentName className, int flags);
+ ServiceInfo getServiceInfo(in ComponentName className, int flags, int userId);
- ProviderInfo getProviderInfo(in ComponentName className, int flags);
+ ProviderInfo getProviderInfo(in ComponentName className, int flags, int userId);
int checkPermission(String permName, String pkgName);
@@ -98,24 +98,24 @@
int getUidForSharedUser(String sharedUserName);
- ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags);
+ ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags, int userId);
List<ResolveInfo> queryIntentActivities(in Intent intent,
- String resolvedType, int flags);
+ String resolvedType, int flags, int userId);
List<ResolveInfo> queryIntentActivityOptions(
in ComponentName caller, in Intent[] specifics,
in String[] specificTypes, in Intent intent,
- String resolvedType, int flags);
+ String resolvedType, int flags, int userId);
List<ResolveInfo> queryIntentReceivers(in Intent intent,
- String resolvedType, int flags);
+ String resolvedType, int flags, int userId);
ResolveInfo resolveService(in Intent intent,
- String resolvedType, int flags);
+ String resolvedType, int flags, int userId);
List<ResolveInfo> queryIntentServices(in Intent intent,
- String resolvedType, int flags);
+ String resolvedType, int flags, int userId);
/**
* This implements getInstalledPackages via a "last returned row"
@@ -131,7 +131,7 @@
* limit that kicks in when flags are included that bloat up the data
* returned.
*/
- ParceledListSlice getInstalledApplications(int flags, in String lastRead);
+ ParceledListSlice getInstalledApplications(int flags, in String lastRead, int userId);
/**
* Retrieve all applications that are marked as persistent.
@@ -141,7 +141,7 @@
*/
List<ApplicationInfo> getPersistentApplications(int flags);
- ProviderInfo resolveContentProvider(String name, int flags);
+ ProviderInfo resolveContentProvider(String name, int flags, int userId);
/**
* Retrieve sync information for all content providers.
@@ -212,28 +212,28 @@
* As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
*/
void setComponentEnabledSetting(in ComponentName componentName,
- in int newState, in int flags);
+ in int newState, in int flags, int userId);
/**
* As per {@link android.content.pm.PackageManager#getComponentEnabledSetting}.
*/
- int getComponentEnabledSetting(in ComponentName componentName);
+ int getComponentEnabledSetting(in ComponentName componentName, int userId);
/**
* As per {@link android.content.pm.PackageManager#setApplicationEnabledSetting}.
*/
- void setApplicationEnabledSetting(in String packageName, in int newState, int flags);
+ void setApplicationEnabledSetting(in String packageName, in int newState, int flags, int userId);
/**
* As per {@link android.content.pm.PackageManager#getApplicationEnabledSetting}.
*/
- int getApplicationEnabledSetting(in String packageName);
+ int getApplicationEnabledSetting(in String packageName, int userId);
/**
* Set whether the given package should be considered stopped, making
* it not visible to implicit intents that filter out stopped packages.
*/
- void setPackageStoppedState(String packageName, boolean stopped);
+ void setPackageStoppedState(String packageName, boolean stopped, int userId);
/**
* Free storage by deleting LRU sorted list of cache files across
@@ -296,7 +296,7 @@
* files need to be deleted
* @param observer a callback used to notify when the operation is completed.
*/
- void clearApplicationUserData(in String packageName, IPackageDataObserver observer);
+ void clearApplicationUserData(in String packageName, IPackageDataObserver observer, int userId);
/**
* Get package statistics including the code, data and cache size for
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 207f077..07d231a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -240,7 +240,13 @@
int gids[], int flags, long firstInstallTime, long lastUpdateTime,
HashSet<String> grantedPermissions) {
- final int userId = Binder.getOrigCallingUser();
+ return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
+ grantedPermissions, UserId.getCallingUserId());
+ }
+
+ static PackageInfo generatePackageInfo(PackageParser.Package p,
+ int gids[], int flags, long firstInstallTime, long lastUpdateTime,
+ HashSet<String> grantedPermissions, int userId) {
PackageInfo pi = new PackageInfo();
pi.packageName = p.packageName;
@@ -3350,7 +3356,7 @@
}
public static ApplicationInfo generateApplicationInfo(Package p, int flags) {
- return generateApplicationInfo(p, flags, UserId.getUserId(Binder.getCallingUid()));
+ return generateApplicationInfo(p, flags, UserId.getCallingUserId());
}
public static ApplicationInfo generateApplicationInfo(Package p, int flags, int userId) {
@@ -3366,6 +3372,13 @@
} else {
p.applicationInfo.flags &= ~ApplicationInfo.FLAG_STOPPED;
}
+ if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+ p.applicationInfo.enabled = true;
+ } else if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+ || p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
+ p.applicationInfo.enabled = false;
+ }
+ p.applicationInfo.enabledSetting = p.mSetEnabled;
return p.applicationInfo;
}
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index e2c222b..bf10bcb 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -211,8 +211,7 @@
SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME);
setPageSize();
- setSyncModeFromConfiguration();
- setJournalModeFromConfiguration();
+ setWalModeFromConfiguration();
setJournalSizeLimit();
setAutoCheckpointInterval();
setLocaleFromConfiguration();
@@ -268,28 +267,69 @@
}
}
- private void setSyncModeFromConfiguration() {
+ private void setWalModeFromConfiguration() {
if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
- final String newValue = mConfiguration.syncMode;
- String value = executeForString("PRAGMA synchronous", null, null);
- if (!value.equalsIgnoreCase(newValue)) {
- execute("PRAGMA synchronous=" + newValue, null, null);
+ if (mConfiguration.walEnabled) {
+ setJournalMode("WAL");
+ setSyncMode(SQLiteGlobal.getWALSyncMode());
+ } else {
+ setJournalMode(SQLiteGlobal.getDefaultJournalMode());
+ setSyncMode(SQLiteGlobal.getDefaultSyncMode());
}
}
}
- private void setJournalModeFromConfiguration() {
- if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
- final String newValue = mConfiguration.journalMode;
- String value = executeForString("PRAGMA journal_mode", null, null);
- if (!value.equalsIgnoreCase(newValue)) {
- value = executeForString("PRAGMA journal_mode=" + newValue, null, null);
- if (!value.equalsIgnoreCase(newValue)) {
- Log.e(TAG, "setting journal_mode to " + newValue
- + " failed for db: " + mConfiguration.label
- + " (on pragma set journal_mode, sqlite returned:" + value);
+ private void setSyncMode(String newValue) {
+ String value = executeForString("PRAGMA synchronous", null, null);
+ if (!canonicalizeSyncMode(value).equalsIgnoreCase(
+ canonicalizeSyncMode(newValue))) {
+ execute("PRAGMA synchronous=" + newValue, null, null);
+ }
+ }
+
+ private static String canonicalizeSyncMode(String value) {
+ if (value.equals("0")) {
+ return "OFF";
+ } else if (value.equals("1")) {
+ return "NORMAL";
+ } else if (value.equals("2")) {
+ return "FULL";
+ }
+ return value;
+ }
+
+ private void setJournalMode(String newValue) {
+ String value = executeForString("PRAGMA journal_mode", null, null);
+ if (!value.equalsIgnoreCase(newValue)) {
+ try {
+ String result = executeForString("PRAGMA journal_mode=" + newValue, null, null);
+ if (result.equalsIgnoreCase(newValue)) {
+ return;
}
+ // PRAGMA journal_mode silently fails and returns the original journal
+ // mode in some cases if the journal mode could not be changed.
+ } catch (SQLiteDatabaseLockedException ex) {
+ // This error (SQLITE_BUSY) occurs if one connection has the database
+ // open in WAL mode and another tries to change it to non-WAL.
}
+ // Because we always disable WAL mode when a database is first opened
+ // (even if we intend to re-enable it), we can encounter problems if
+ // there is another open connection to the database somewhere.
+ // This can happen for a variety of reasons such as an application opening
+ // the same database in multiple processes at the same time or if there is a
+ // crashing content provider service that the ActivityManager has
+ // removed from its registry but whose process hasn't quite died yet
+ // by the time it is restarted in a new process.
+ //
+ // If we don't change the journal mode, nothing really bad happens.
+ // In the worst case, an application that enables WAL might not actually
+ // get it, although it can still use connection pooling.
+ Log.w(TAG, "Could not change the database journal mode of '"
+ + mConfiguration.label + "' from '" + value + "' to '" + newValue
+ + "' because the database is locked. This usually means that "
+ + "there are other open connections to the database which prevents "
+ + "the database from enabling or disabling write-ahead logging mode. "
+ + "Proceeding without changing the journal mode.");
}
}
@@ -349,10 +389,7 @@
}
// Remember what changed.
- boolean syncModeChanged = !configuration.syncMode.equalsIgnoreCase(
- mConfiguration.syncMode);
- boolean journalModeChanged = !configuration.journalMode.equalsIgnoreCase(
- mConfiguration.journalMode);
+ boolean walModeChanged = configuration.walEnabled != mConfiguration.walEnabled;
boolean localeChanged = !configuration.locale.equals(mConfiguration.locale);
// Update configuration parameters.
@@ -361,14 +398,9 @@
// Update prepared statement cache size.
mPreparedStatementCache.resize(configuration.maxSqlCacheSize);
- // Update sync mode.
- if (syncModeChanged) {
- setSyncModeFromConfiguration();
- }
-
- // Update journal mode.
- if (journalModeChanged) {
- setJournalModeFromConfiguration();
+ // Update WAL.
+ if (walModeChanged) {
+ setWalModeFromConfiguration();
}
// Update locale.
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index 3562e89..27c9ee5 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -257,7 +257,33 @@
synchronized (mLock) {
throwIfClosedLocked();
+ boolean restrictToOneConnection = false;
+ if (mConfiguration.walEnabled != configuration.walEnabled) {
+ // WAL mode can only be changed if there are no acquired connections
+ // because we need to close all but the primary connection first.
+ if (!mAcquiredConnections.isEmpty()) {
+ throw new IllegalStateException("Write Ahead Logging (WAL) mode cannot "
+ + "be enabled or disabled while there are transactions in "
+ + "progress. Finish all transactions and release all active "
+ + "database connections first.");
+ }
+
+ // Close all non-primary connections. This should happen immediately
+ // because none of them are in use.
+ closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked();
+ assert mAvailableNonPrimaryConnections.isEmpty();
+
+ restrictToOneConnection = true;
+ }
+
if (mConfiguration.openFlags != configuration.openFlags) {
+ // If we are changing open flags and WAL mode at the same time, then
+ // we have no choice but to close the primary connection beforehand
+ // because there can only be one connection open when we change WAL mode.
+ if (restrictToOneConnection) {
+ closeAvailableConnectionsAndLogExceptionsLocked();
+ }
+
// Try to reopen the primary connection using the new open flags then
// close and discard all existing connections.
// This might throw if the database is corrupt or cannot be opened in
@@ -453,11 +479,7 @@
// Can't throw.
private void closeAvailableConnectionsAndLogExceptionsLocked() {
- final int count = mAvailableNonPrimaryConnections.size();
- for (int i = 0; i < count; i++) {
- closeConnectionAndLogExceptionsLocked(mAvailableNonPrimaryConnections.get(i));
- }
- mAvailableNonPrimaryConnections.clear();
+ closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked();
if (mAvailablePrimaryConnection != null) {
closeConnectionAndLogExceptionsLocked(mAvailablePrimaryConnection);
@@ -466,6 +488,15 @@
}
// Can't throw.
+ private void closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked() {
+ final int count = mAvailableNonPrimaryConnections.size();
+ for (int i = 0; i < count; i++) {
+ closeConnectionAndLogExceptionsLocked(mAvailableNonPrimaryConnections.get(i));
+ }
+ mAvailableNonPrimaryConnections.clear();
+ }
+
+ // Can't throw.
private void closeExcessConnectionsAndLogExceptionsLocked() {
int availableCount = mAvailableNonPrimaryConnections.size();
while (availableCount-- > mConfiguration.maxConnectionPoolSize - 1) {
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index bf32ea7..0ecce4d 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -127,10 +127,6 @@
// INVARIANT: Guarded by mLock.
private boolean mHasAttachedDbsLocked;
- // True if the database is in WAL mode.
- // INVARIANT: Guarded by mLock.
- private boolean mIsWALEnabledLocked;
-
/**
* When a constraint violation occurs, an immediate ROLLBACK occurs,
* thus ending the current transaction, and the command aborts with a
@@ -834,8 +830,14 @@
synchronized (mLock) {
throwIfNotOpenLocked();
+
mConfigurationLocked.customFunctions.add(wrapper);
- mConnectionPoolLocked.reconfigure(mConfigurationLocked);
+ try {
+ mConnectionPoolLocked.reconfigure(mConfigurationLocked);
+ } catch (RuntimeException ex) {
+ mConfigurationLocked.customFunctions.remove(wrapper);
+ throw ex;
+ }
}
}
@@ -1733,8 +1735,15 @@
synchronized (mLock) {
throwIfNotOpenLocked();
+
+ final Locale oldLocale = mConfigurationLocked.locale;
mConfigurationLocked.locale = locale;
- mConnectionPoolLocked.reconfigure(mConfigurationLocked);
+ try {
+ mConnectionPoolLocked.reconfigure(mConfigurationLocked);
+ } catch (RuntimeException ex) {
+ mConfigurationLocked.locale = oldLocale;
+ throw ex;
+ }
}
}
@@ -1759,8 +1768,15 @@
synchronized (mLock) {
throwIfNotOpenLocked();
+
+ final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
mConfigurationLocked.maxSqlCacheSize = cacheSize;
- mConnectionPoolLocked.reconfigure(mConfigurationLocked);
+ try {
+ mConnectionPoolLocked.reconfigure(mConfigurationLocked);
+ } catch (RuntimeException ex) {
+ mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
+ throw ex;
+ }
}
}
@@ -1805,12 +1821,16 @@
* </p>
*
* @return true if write-ahead-logging is set. false otherwise
+ *
+ * @throws IllegalStateException if there are transactions in progress at the
+ * time this method is called. WAL mode can only be changed when there are no
+ * transactions in progress.
*/
public boolean enableWriteAheadLogging() {
synchronized (mLock) {
throwIfNotOpenLocked();
- if (mIsWALEnabledLocked) {
+ if (mConfigurationLocked.walEnabled) {
return true;
}
@@ -1835,32 +1855,45 @@
return false;
}
- mIsWALEnabledLocked = true;
+ final int oldMaxConnectionPoolSize = mConfigurationLocked.maxConnectionPoolSize;
mConfigurationLocked.maxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
- mConfigurationLocked.syncMode = SQLiteGlobal.getWALSyncMode();
- mConfigurationLocked.journalMode = "WAL";
- mConnectionPoolLocked.reconfigure(mConfigurationLocked);
+ mConfigurationLocked.walEnabled = true;
+ try {
+ mConnectionPoolLocked.reconfigure(mConfigurationLocked);
+ } catch (RuntimeException ex) {
+ mConfigurationLocked.maxConnectionPoolSize = oldMaxConnectionPoolSize;
+ mConfigurationLocked.walEnabled = false;
+ throw ex;
+ }
}
return true;
}
/**
* This method disables the features enabled by {@link #enableWriteAheadLogging()}.
- * @hide
+ *
+ * @throws IllegalStateException if there are transactions in progress at the
+ * time this method is called. WAL mode can only be changed when there are no
+ * transactions in progress.
*/
public void disableWriteAheadLogging() {
synchronized (mLock) {
throwIfNotOpenLocked();
- if (!mIsWALEnabledLocked) {
+ if (!mConfigurationLocked.walEnabled) {
return;
}
- mIsWALEnabledLocked = false;
+ final int oldMaxConnectionPoolSize = mConfigurationLocked.maxConnectionPoolSize;
mConfigurationLocked.maxConnectionPoolSize = 1;
- mConfigurationLocked.syncMode = SQLiteGlobal.getDefaultSyncMode();
- mConfigurationLocked.journalMode = SQLiteGlobal.getDefaultJournalMode();
- mConnectionPoolLocked.reconfigure(mConfigurationLocked);
+ mConfigurationLocked.walEnabled = false;
+ try {
+ mConnectionPoolLocked.reconfigure(mConfigurationLocked);
+ } catch (RuntimeException ex) {
+ mConfigurationLocked.maxConnectionPoolSize = oldMaxConnectionPoolSize;
+ mConfigurationLocked.walEnabled = true;
+ throw ex;
+ }
}
}
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index efbcaca..e06a5ee 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -85,18 +85,11 @@
public Locale locale;
/**
- * The database synchronization mode.
+ * True if WAL mode is enabled.
*
- * Default is {@link SQLiteGlobal#getDefaultSyncMode()}.
+ * Default is false.
*/
- public String syncMode;
-
- /**
- * The database journal mode.
- *
- * Default is {@link SQLiteGlobal#getDefaultJournalMode()}.
- */
- public String journalMode;
+ public boolean walEnabled;
/**
* The custom functions to register.
@@ -124,8 +117,6 @@
maxConnectionPoolSize = 1;
maxSqlCacheSize = 25;
locale = Locale.getDefault();
- syncMode = SQLiteGlobal.getDefaultSyncMode();
- journalMode = SQLiteGlobal.getDefaultJournalMode();
}
/**
@@ -162,8 +153,7 @@
maxConnectionPoolSize = other.maxConnectionPoolSize;
maxSqlCacheSize = other.maxSqlCacheSize;
locale = other.locale;
- syncMode = other.syncMode;
- journalMode = other.journalMode;
+ walEnabled = other.walEnabled;
customFunctions.clear();
customFunctions.addAll(other.customFunctions);
}
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 442535a..89c9c36 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -30,8 +30,8 @@
interface INetworkPolicyManager {
/** Control UID policies. */
- void setUidPolicy(int uid, int policy);
- int getUidPolicy(int uid);
+ void setAppPolicy(int appId, int policy);
+ int getAppPolicy(int appId);
boolean isUidForeground(int uid);
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 7173751..c09c676 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -88,21 +88,21 @@
}
/**
- * Set policy flags for specific UID.
+ * Set policy flags for specific application.
*
* @param policy {@link #POLICY_NONE} or combination of flags like
* {@link #POLICY_REJECT_METERED_BACKGROUND}.
*/
- public void setUidPolicy(int uid, int policy) {
+ public void setAppPolicy(int appId, int policy) {
try {
- mService.setUidPolicy(uid, policy);
+ mService.setAppPolicy(appId, policy);
} catch (RemoteException e) {
}
}
- public int getUidPolicy(int uid) {
+ public int getAppPolicy(int appId) {
try {
- return mService.getUidPolicy(uid);
+ return mService.getAppPolicy(appId);
} catch (RemoteException e) {
return POLICY_NONE;
}
@@ -203,6 +203,7 @@
* Check if given UID can have a {@link #setUidPolicy(int, int)} defined,
* usually to protect critical system services.
*/
+ @Deprecated
public static boolean isUidValidForPolicy(Context context, int uid) {
// first, quick-reject non-applications
if (uid < android.os.Process.FIRST_APPLICATION_UID
diff --git a/core/java/android/os/UserId.java b/core/java/android/os/UserId.java
index 0da67d63..8bf6c6e 100644
--- a/core/java/android/os/UserId.java
+++ b/core/java/android/os/UserId.java
@@ -61,6 +61,15 @@
return uid >= Process.FIRST_ISOLATED_UID && uid <= Process.LAST_ISOLATED_UID;
}
+ public static boolean isApp(int uid) {
+ if (uid > 0) {
+ uid = UserId.getAppId(uid);
+ return uid >= Process.FIRST_APPLICATION_UID && uid <= Process.LAST_APPLICATION_UID;
+ } else {
+ return false;
+ }
+ }
+
/**
* Returns the user id for a given uid.
* @hide
@@ -96,4 +105,12 @@
public static final int getAppId(int uid) {
return uid % PER_USER_RANGE;
}
+
+ /**
+ * Returns the user id of the current process
+ * @return user id of the current process
+ */
+ public static final int myUserId() {
+ return getUserId(Process.myUid());
+ }
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index fbb3273..d74ccb8 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -793,6 +793,7 @@
MOVED_TO_SECURE.add(Secure.HTTP_PROXY);
MOVED_TO_SECURE.add(Secure.INSTALL_NON_MARKET_APPS);
MOVED_TO_SECURE.add(Secure.LOCATION_PROVIDERS_ALLOWED);
+ MOVED_TO_SECURE.add(Secure.LOCK_BIOMETRIC_WEAK_FLAGS);
MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_ENABLED);
MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_VISIBLE);
MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
@@ -2657,6 +2658,13 @@
public static final String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
/**
+ * A flag containing settings used for biometric weak
+ * @hide
+ */
+ public static final String LOCK_BIOMETRIC_WEAK_FLAGS =
+ "lock_biometric_weak_flags";
+
+ /**
* Whether autolock is enabled (0 = false, 1 = true)
*/
public static final String LOCK_PATTERN_ENABLED = "lock_pattern_autolock";
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index fecc8f9..850349b 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -46,6 +46,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.res.Resources;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -554,12 +555,15 @@
private synchronized void updateSdpRecords() {
ArrayList<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
- // Add the default records
- uuids.add(BluetoothUuid.HSP_AG);
- uuids.add(BluetoothUuid.ObexObjectPush);
+ Resources R = mContext.getResources();
- if (mContext.getResources().
- getBoolean(com.android.internal.R.bool.config_voice_capable)) {
+ // Add the default records
+ if (R.getBoolean(com.android.internal.R.bool.config_bluetooth_default_profiles)) {
+ uuids.add(BluetoothUuid.HSP_AG);
+ uuids.add(BluetoothUuid.ObexObjectPush);
+ }
+
+ if (R.getBoolean(com.android.internal.R.bool.config_voice_capable)) {
uuids.add(BluetoothUuid.Handsfree_AG);
uuids.add(BluetoothUuid.PBAP_PSE);
}
@@ -567,14 +571,16 @@
// Add SDP records for profiles maintained by Android userspace
addReservedSdpRecords(uuids);
- // Enable profiles maintained by Bluez userspace.
- setBluetoothTetheringNative(true, BluetoothPanProfileHandler.NAP_ROLE,
- BluetoothPanProfileHandler.NAP_BRIDGE);
+ if (R.getBoolean(com.android.internal.R.bool.config_bluetooth_default_profiles)) {
+ // Enable profiles maintained by Bluez userspace.
+ setBluetoothTetheringNative(true, BluetoothPanProfileHandler.NAP_ROLE,
+ BluetoothPanProfileHandler.NAP_BRIDGE);
- // Add SDP records for profiles maintained by Bluez userspace
- uuids.add(BluetoothUuid.AudioSource);
- uuids.add(BluetoothUuid.AvrcpTarget);
- uuids.add(BluetoothUuid.NAP);
+ // Add SDP records for profiles maintained by Bluez userspace
+ uuids.add(BluetoothUuid.AudioSource);
+ uuids.add(BluetoothUuid.AvrcpTarget);
+ uuids.add(BluetoothUuid.NAP);
+ }
// Cannot cast uuids.toArray directly since ParcelUuid is parcelable
mAdapterUuids = new ParcelUuid[uuids.size()];
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 92e8f4e..77fd8d2 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1654,14 +1654,22 @@
}
}
}
-
+
/**
- * Scales down the coordination of this event by the given scale.
+ * Applies a scale factor to all points within this event.
*
+ * This method is used to adjust touch events to simulate different density
+ * displays for compatibility mode. The values returned by {@link #getRawX()},
+ * {@link #getRawY()}, {@link #getXPrecision()} and {@link #getYPrecision()}
+ * are also affected by the scale factor.
+ *
+ * @param scale The scale factor to apply.
* @hide
*/
public final void scale(float scale) {
- nativeScale(mNativePtr, scale);
+ if (scale != 1.0f) {
+ nativeScale(mNativePtr, scale);
+ }
}
/** {@inheritDoc} */
@@ -2631,7 +2639,9 @@
* @param deltaY Amount to add to the current Y coordinate of the event.
*/
public final void offsetLocation(float deltaX, float deltaY) {
- nativeOffsetLocation(mNativePtr, deltaX, deltaY);
+ if (deltaX != 0.0f || deltaY != 0.0f) {
+ nativeOffsetLocation(mNativePtr, deltaX, deltaY);
+ }
}
/**
@@ -2644,7 +2654,7 @@
public final void setLocation(float x, float y) {
float oldX = getX();
float oldY = getY();
- nativeOffsetLocation(mNativePtr, x - oldX, y - oldY);
+ offsetLocation(x - oldX, y - oldY);
}
/**
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index edaa262..eb80290d 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -20,6 +20,7 @@
import android.graphics.*;
import android.os.Parcelable;
import android.os.Parcel;
+import android.os.SystemProperties;
import android.util.Log;
/**
@@ -35,6 +36,15 @@
public static final int ROTATION_180 = 2;
public static final int ROTATION_270 = 3;
+ private static final boolean headless = "1".equals(
+ SystemProperties.get("ro.config.headless", "0"));
+
+ private static void checkHeadless() {
+ if(headless) {
+ throw new UnsupportedOperationException("Device is headless");
+ }
+ }
+
/**
* Create Surface from a {@link SurfaceTexture}.
*
@@ -46,6 +56,8 @@
* Surface.
*/
public Surface(SurfaceTexture surfaceTexture) {
+ checkHeadless();
+
if (DEBUG_RELEASE) {
mCreationStack = new Exception();
}
@@ -244,6 +256,8 @@
public Surface(SurfaceSession s,
int pid, int display, int w, int h, int format, int flags)
throws OutOfResourcesException {
+ checkHeadless();
+
if (DEBUG_RELEASE) {
mCreationStack = new Exception();
}
@@ -255,6 +269,8 @@
public Surface(SurfaceSession s,
int pid, String name, int display, int w, int h, int format, int flags)
throws OutOfResourcesException {
+ checkHeadless();
+
if (DEBUG_RELEASE) {
mCreationStack = new Exception();
}
@@ -269,6 +285,8 @@
* @hide
*/
public Surface() {
+ checkHeadless();
+
if (DEBUG_RELEASE) {
mCreationStack = new Exception();
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d403cb9e..ffffc73 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1459,7 +1459,7 @@
* apps.
* @hide
*/
- public static final boolean USE_DISPLAY_LIST_PROPERTIES = true;
+ public static final boolean USE_DISPLAY_LIST_PROPERTIES = false;
/**
* Map used to store views' tags.
diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java
index 7e38570..c41bc00 100644
--- a/core/java/android/webkit/WebSettingsClassic.java
+++ b/core/java/android/webkit/WebSettingsClassic.java
@@ -121,9 +121,6 @@
private boolean mForceUserScalable = false;
// AutoFill Profile data
- /**
- * @hide for now, pending API council approval.
- */
public static class AutoFillProfile {
private int mUniqueId;
private String mFullName;
@@ -644,7 +641,6 @@
/**
* Set the double-tap zoom of the page in percent. Default is 100.
* @param doubleTapZoom A percent value for increasing or decreasing the double-tap zoom.
- * @hide
*/
public void setDoubleTapZoom(int doubleTapZoom) {
if (mDoubleTapZoom != doubleTapZoom) {
@@ -656,7 +652,6 @@
/**
* Get the double-tap zoom of the page in percent.
* @return A percent value describing the double-tap zoom.
- * @hide
*/
public int getDoubleTapZoom() {
return mDoubleTapZoom;
@@ -1012,7 +1007,6 @@
/**
* Set the number of pages cached by the WebKit for the history navigation.
* @param size A non-negative integer between 0 (no cache) and 20 (max).
- * @hide
*/
public synchronized void setPageCacheCapacity(int size) {
if (size < 0) size = 0;
@@ -1108,7 +1102,6 @@
/**
* Tell the WebView to use Skia's hardware accelerated rendering path
* @param flag True if the WebView should use Skia's hw-accel path
- * @hide
*/
public synchronized void setHardwareAccelSkiaEnabled(boolean flag) {
if (mHardwareAccelSkia != flag) {
@@ -1119,7 +1112,6 @@
/**
* @return True if the WebView is using hardware accelerated skia
- * @hide
*/
public synchronized boolean getHardwareAccelSkiaEnabled() {
return mHardwareAccelSkia;
@@ -1128,7 +1120,6 @@
/**
* Tell the WebView to show the visual indicator
* @param flag True if the WebView should show the visual indicator
- * @hide
*/
public synchronized void setShowVisualIndicator(boolean flag) {
if (mShowVisualIndicator != flag) {
@@ -1139,7 +1130,6 @@
/**
* @return True if the WebView is showing the visual indicator
- * @hide
*/
public synchronized boolean getShowVisualIndicator() {
return mShowVisualIndicator;
@@ -1283,7 +1273,6 @@
* @param flag True if the WebView should enable WebWorkers.
* Note that this flag only affects V8. JSC does not have
* an equivalent setting.
- * @hide
*/
public synchronized void setWorkersEnabled(boolean flag) {
if (mWorkersEnabled != flag) {
@@ -1305,8 +1294,8 @@
/**
* Sets whether XSS Auditor is enabled.
+ * Only used by LayoutTestController.
* @param flag Whether XSS Auditor should be enabled.
- * @hide Only used by LayoutTestController.
*/
public synchronized void setXSSAuditorEnabled(boolean flag) {
if (mXSSAuditorEnabled != flag) {
@@ -1507,7 +1496,6 @@
* of an HTML page to fit the screen. This conflicts with attempts by
* the UI to zoom in and out of an image, so it is set false by default.
* @param shrink Set true to let webkit shrink the standalone image to fit.
- * {@hide}
*/
public void setShrinksStandaloneImagesToFit(boolean shrink) {
if (mShrinksStandaloneImagesToFit != shrink) {
@@ -1520,7 +1508,6 @@
* Specify the maximum decoded image size. The default is
* 2 megs for small memory devices and 8 megs for large memory devices.
* @param size The maximum decoded size, or zero to set to the default.
- * @hide
*/
public void setMaximumDecodedImageSize(long size) {
if (mMaximumDecodedImageSize != size) {
@@ -1562,7 +1549,6 @@
/**
* Returns whether the viewport metatag can disable zooming
- * @hide
*/
public boolean forceUserScalable() {
return mForceUserScalable;
@@ -1571,7 +1557,6 @@
/**
* Sets whether viewport metatag can disable zooming.
* @param flag Whether or not to forceably enable user scalable.
- * @hide
*/
public synchronized void setForceUserScalable(boolean flag) {
mForceUserScalable = flag;
@@ -1584,9 +1569,6 @@
}
}
- /**
- * @hide
- */
public synchronized void setAutoFillEnabled(boolean enabled) {
// AutoFill is always disabled in private browsing mode.
boolean autoFillEnabled = enabled && !mPrivateBrowsingEnabled;
@@ -1596,16 +1578,10 @@
}
}
- /**
- * @hide
- */
public synchronized boolean getAutoFillEnabled() {
return mAutoFillEnabled;
}
- /**
- * @hide
- */
public synchronized void setAutoFillProfile(AutoFillProfile profile) {
if (mAutoFillProfile != profile) {
mAutoFillProfile = profile;
@@ -1613,9 +1589,6 @@
}
}
- /**
- * @hide
- */
public synchronized AutoFillProfile getAutoFillProfile() {
return mAutoFillProfile;
}
@@ -1633,18 +1606,12 @@
}
}
- /**
- * @hide
- */
public void setProperty(String key, String value) {
if (mWebView.nativeSetProperty(key, value)) {
mWebView.invalidate();
}
}
- /**
- * @hide
- */
public String getProperty(String key) {
return mWebView.nativeGetProperty(key);
}
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index e553a2e..03329b8 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -348,8 +348,6 @@
*
* @hide
*/
-// TODO: Remove duplicated API documentation and @hide from fields and methods, and
-// checkThread() call. (All left in for now to ease branch merging.)
// TODO: Check if any WebView published API methods are called from within here, and if so
// we should bounce the call out via the proxy to enable any sub-class to override it.
@Widget
@@ -1464,8 +1462,6 @@
*/
@Override
public void init(Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
- checkThread();
-
Context context = mContext;
// Used by the chrome stack to find application paths
@@ -1497,8 +1493,7 @@
mEditTextScroller = new Scroller(context);
}
- // === START: WebView Proxy binding ===
- // Keep the webview proxy / SPI related stuff in this section, to minimize merge conflicts.
+ // WebViewProvider bindings
static class Factory implements WebViewFactoryProvider, WebViewFactoryProvider.Statics {
@Override
@@ -1587,8 +1582,6 @@
mWebViewPrivate.setScrollYRaw(mScrollY);
}
- // === END: WebView Proxy binding ===
-
private static class TrustStorageListener extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
@@ -1969,7 +1962,6 @@
*/
@Override
public void setHorizontalScrollbarOverlay(boolean overlay) {
- checkThread();
mOverlayHorizontalScrollbar = overlay;
}
@@ -1978,7 +1970,6 @@
*/
@Override
public void setVerticalScrollbarOverlay(boolean overlay) {
- checkThread();
mOverlayVerticalScrollbar = overlay;
}
@@ -1987,7 +1978,6 @@
*/
@Override
public boolean overlayHorizontalScrollbar() {
- checkThread();
return mOverlayHorizontalScrollbar;
}
@@ -1996,7 +1986,6 @@
*/
@Override
public boolean overlayVerticalScrollbar() {
- checkThread();
return mOverlayVerticalScrollbar;
}
@@ -2022,7 +2011,6 @@
/**
* Returns the height (in pixels) of the embedded title bar (if any). Does not care about
* scrolling
- * @hide
*/
protected int getTitleHeight() {
if (mWebView instanceof TitleBarDelegate) {
@@ -2039,7 +2027,6 @@
public int getVisibleTitleHeight() {
// Actually, this method returns the height of the embedded title bar if one is set via the
// hidden setEmbeddedTitleBar method.
- checkThread();
return getVisibleTitleHeightImpl();
}
@@ -2085,7 +2072,6 @@
*/
@Override
public SslCertificate getCertificate() {
- checkThread();
return mCertificate;
}
@@ -2094,7 +2080,6 @@
*/
@Override
public void setCertificate(SslCertificate certificate) {
- checkThread();
if (DebugFlags.WEB_VIEW) {
Log.v(LOGTAG, "setCertificate=" + certificate);
}
@@ -2111,7 +2096,6 @@
*/
@Override
public void savePassword(String host, String username, String password) {
- checkThread();
mDatabase.setUsernamePassword(host, username, password);
}
@@ -2121,7 +2105,6 @@
@Override
public void setHttpAuthUsernamePassword(String host, String realm,
String username, String password) {
- checkThread();
mDatabase.setHttpAuthUsernamePassword(host, realm, username, password);
}
@@ -2130,7 +2113,6 @@
*/
@Override
public String[] getHttpAuthUsernamePassword(String host, String realm) {
- checkThread();
return mDatabase.getHttpAuthUsernamePassword(host, realm);
}
@@ -2170,7 +2152,6 @@
*/
@Override
public void destroy() {
- checkThread();
destroyImpl();
}
@@ -2203,7 +2184,6 @@
*/
@Deprecated
public static void enablePlatformNotifications() {
- checkThread();
synchronized (WebViewClassic.class) {
sNotificationsEnabled = true;
Context context = JniUtil.getContext();
@@ -2217,7 +2197,6 @@
*/
@Deprecated
public static void disablePlatformNotifications() {
- checkThread();
synchronized (WebViewClassic.class) {
sNotificationsEnabled = false;
Context context = JniUtil.getContext();
@@ -2231,10 +2210,9 @@
*
* @param flags JS engine flags in a String
*
- * @hide This is an implementation detail.
+ * This is an implementation detail.
*/
public void setJsFlags(String flags) {
- checkThread();
mWebViewCore.sendMessage(EventHub.SET_JS_FLAGS, flags);
}
@@ -2243,17 +2221,14 @@
*/
@Override
public void setNetworkAvailable(boolean networkUp) {
- checkThread();
mWebViewCore.sendMessage(EventHub.SET_NETWORK_STATE,
networkUp ? 1 : 0, 0);
}
/**
* Inform WebView about the current network type.
- * {@hide}
*/
public void setNetworkType(String type, String subtype) {
- checkThread();
Map<String, String> map = new HashMap<String, String>();
map.put("type", type);
map.put("subtype", subtype);
@@ -2265,7 +2240,6 @@
*/
@Override
public WebBackForwardList saveState(Bundle outState) {
- checkThread();
if (outState == null) {
return null;
}
@@ -2317,7 +2291,6 @@
@Override
@Deprecated
public boolean savePicture(Bundle b, final File dest) {
- checkThread();
if (dest == null || b == null) {
return false;
}
@@ -2379,7 +2352,6 @@
@Override
@Deprecated
public boolean restorePicture(Bundle b, File src) {
- checkThread();
if (src == null || b == null) {
return false;
}
@@ -2425,7 +2397,6 @@
* of WebView.
* @param stream The {@link OutputStream} to save to
* @return True if saved successfully
- * @hide
*/
public boolean saveViewState(OutputStream stream) {
try {
@@ -2441,7 +2412,6 @@
* {@link #saveViewState(OutputStream)} for more information.
* @param stream The {@link InputStream} to load from
* @return True if loaded successfully
- * @hide
*/
public boolean loadViewState(InputStream stream) {
try {
@@ -2471,7 +2441,6 @@
*/
@Override
public WebBackForwardList restoreState(Bundle inState) {
- checkThread();
WebBackForwardList returnList = null;
if (inState == null) {
return returnList;
@@ -2528,7 +2497,6 @@
*/
@Override
public void loadUrl(String url, Map<String, String> additionalHttpHeaders) {
- checkThread();
loadUrlImpl(url, additionalHttpHeaders);
}
@@ -2546,7 +2514,6 @@
*/
@Override
public void loadUrl(String url) {
- checkThread();
loadUrlImpl(url);
}
@@ -2562,7 +2529,6 @@
*/
@Override
public void postUrl(String url, byte[] postData) {
- checkThread();
if (URLUtil.isNetworkUrl(url)) {
switchOutDrawHistory();
WebViewCore.PostUrlData arg = new WebViewCore.PostUrlData();
@@ -2580,7 +2546,6 @@
*/
@Override
public void loadData(String data, String mimeType, String encoding) {
- checkThread();
loadDataImpl(data, mimeType, encoding);
}
@@ -2601,7 +2566,6 @@
@Override
public void loadDataWithBaseURL(String baseUrl, String data,
String mimeType, String encoding, String historyUrl) {
- checkThread();
if (baseUrl != null && baseUrl.toLowerCase().startsWith("data:")) {
loadDataImpl(data, mimeType, encoding);
@@ -2623,7 +2587,6 @@
*/
@Override
public void saveWebArchive(String filename) {
- checkThread();
saveWebArchiveImpl(filename, false, null);
}
@@ -2645,7 +2608,6 @@
*/
@Override
public void saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback) {
- checkThread();
saveWebArchiveImpl(basename, autoname, callback);
}
@@ -2660,7 +2622,6 @@
*/
@Override
public void stopLoading() {
- checkThread();
// TODO: should we clear all the messages in the queue before sending
// STOP_LOADING?
switchOutDrawHistory();
@@ -2672,7 +2633,6 @@
*/
@Override
public void reload() {
- checkThread();
clearHelpers();
switchOutDrawHistory();
mWebViewCore.sendMessage(EventHub.RELOAD);
@@ -2683,7 +2643,6 @@
*/
@Override
public boolean canGoBack() {
- checkThread();
WebBackForwardList l = mCallbackProxy.getBackForwardList();
synchronized (l) {
if (l.getClearPending()) {
@@ -2699,7 +2658,6 @@
*/
@Override
public void goBack() {
- checkThread();
goBackOrForwardImpl(-1);
}
@@ -2708,7 +2666,6 @@
*/
@Override
public boolean canGoForward() {
- checkThread();
WebBackForwardList l = mCallbackProxy.getBackForwardList();
synchronized (l) {
if (l.getClearPending()) {
@@ -2724,7 +2681,6 @@
*/
@Override
public void goForward() {
- checkThread();
goBackOrForwardImpl(1);
}
@@ -2733,7 +2689,6 @@
*/
@Override
public boolean canGoBackOrForward(int steps) {
- checkThread();
WebBackForwardList l = mCallbackProxy.getBackForwardList();
synchronized (l) {
if (l.getClearPending()) {
@@ -2750,7 +2705,6 @@
*/
@Override
public void goBackOrForward(int steps) {
- checkThread();
goBackOrForwardImpl(steps);
}
@@ -2771,7 +2725,6 @@
*/
@Override
public boolean isPrivateBrowsingEnabled() {
- checkThread();
return getSettings().isPrivateBrowsingEnabled();
}
@@ -2793,7 +2746,6 @@
*/
@Override
public boolean pageUp(boolean top) {
- checkThread();
if (mNativeClass == 0) {
return false;
}
@@ -2818,7 +2770,6 @@
*/
@Override
public boolean pageDown(boolean bottom) {
- checkThread();
if (mNativeClass == 0) {
return false;
}
@@ -2842,7 +2793,6 @@
*/
@Override
public void clearView() {
- checkThread();
mContentWidth = 0;
mContentHeight = 0;
setBaseLayer(0, null, false, false);
@@ -2854,7 +2804,6 @@
*/
@Override
public Picture capturePicture() {
- checkThread();
if (mNativeClass == 0) return null;
Picture result = new Picture();
nativeCopyBaseContentToPicture(result);
@@ -2866,7 +2815,6 @@
*/
@Override
public float getScale() {
- checkThread();
return mZoomManager.getScale();
}
@@ -2884,7 +2832,6 @@
*/
@Override
public void setInitialScale(int scaleInPercent) {
- checkThread();
mZoomManager.setInitialScaleInPercent(scaleInPercent);
}
@@ -2893,7 +2840,6 @@
*/
@Override
public void invokeZoomPicker() {
- checkThread();
if (!getSettings().supportZoom()) {
Log.w(LOGTAG, "This WebView doesn't support zoom.");
return;
@@ -2907,7 +2853,6 @@
*/
@Override
public HitTestResult getHitTestResult() {
- checkThread();
return mInitialHitTestResult;
}
@@ -2943,7 +2888,6 @@
*/
@Override
public void requestFocusNodeHref(Message hrefMsg) {
- checkThread();
if (hrefMsg == null) {
return;
}
@@ -2966,7 +2910,6 @@
*/
@Override
public void requestImageRef(Message msg) {
- checkThread();
if (0 == mNativeClass) return; // client isn't initialized
String url = mFocusedNode != null ? mFocusedNode.mImageUrl : null;
Bundle data = msg.getData();
@@ -3020,7 +2963,6 @@
* along with it vertically, while remaining in view horizontally. Pass
* null to remove the title bar from the WebView, and return to drawing
* the WebView normally without translating to account for the title bar.
- * @hide
*/
public void setEmbeddedTitleBar(View v) {
if (mWebView instanceof TitleBarDelegate) {
@@ -3042,7 +2984,6 @@
* Set where to render the embedded title bar
* NO_GRAVITY at the top of the page
* TOP at the top of the screen
- * @hide
*/
public void setTitleBarGravity(int gravity) {
mTitleGravity = gravity;
@@ -3422,7 +3363,6 @@
return getViewHeight();
}
- /** @hide */
@Override
public void onDrawVerticalScrollBar(Canvas canvas,
Drawable scrollBar,
@@ -3471,7 +3411,6 @@
*/
@Override
public String getUrl() {
- checkThread();
WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
return h != null ? h.getUrl() : null;
}
@@ -3481,7 +3420,6 @@
*/
@Override
public String getOriginalUrl() {
- checkThread();
WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
return h != null ? h.getOriginalUrl() : null;
}
@@ -3491,7 +3429,6 @@
*/
@Override
public String getTitle() {
- checkThread();
WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
return h != null ? h.getTitle() : null;
}
@@ -3501,7 +3438,6 @@
*/
@Override
public Bitmap getFavicon() {
- checkThread();
WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
return h != null ? h.getFavicon() : null;
}
@@ -3520,7 +3456,6 @@
*/
@Override
public int getProgress() {
- checkThread();
return mCallbackProxy.getProgress();
}
@@ -3529,7 +3464,6 @@
*/
@Override
public int getContentHeight() {
- checkThread();
return mContentHeight;
}
@@ -3541,9 +3475,6 @@
return mContentWidth;
}
- /**
- * @hide
- */
public int getPageBackgroundColor() {
return nativeGetBackgroundColor();
}
@@ -3553,7 +3484,6 @@
*/
@Override
public void pauseTimers() {
- checkThread();
mWebViewCore.sendMessage(EventHub.PAUSE_TIMERS);
}
@@ -3562,7 +3492,6 @@
*/
@Override
public void resumeTimers() {
- checkThread();
mWebViewCore.sendMessage(EventHub.RESUME_TIMERS);
}
@@ -3571,7 +3500,6 @@
*/
@Override
public void onPause() {
- checkThread();
if (!mIsPaused) {
mIsPaused = true;
mWebViewCore.sendMessage(EventHub.ON_PAUSE);
@@ -3610,7 +3538,6 @@
*/
@Override
public void onResume() {
- checkThread();
if (mIsPaused) {
mIsPaused = false;
mWebViewCore.sendMessage(EventHub.ON_RESUME);
@@ -3642,7 +3569,6 @@
*/
@Override
public void freeMemory() {
- checkThread();
mWebViewCore.sendMessage(EventHub.FREE_MEMORY);
}
@@ -3651,7 +3577,6 @@
*/
@Override
public void clearCache(boolean includeDiskFiles) {
- checkThread();
// Note: this really needs to be a static method as it clears cache for all
// WebView. But we need mWebViewCore to send message to WebCore thread, so
// we can't make this static.
@@ -3664,7 +3589,6 @@
*/
@Override
public void clearFormData() {
- checkThread();
if (mAutoCompletePopup != null) {
mAutoCompletePopup.clearAdapter();
}
@@ -3675,7 +3599,6 @@
*/
@Override
public void clearHistory() {
- checkThread();
mCallbackProxy.getBackForwardList().setClearPending();
mWebViewCore.sendMessage(EventHub.CLEAR_HISTORY);
}
@@ -3685,7 +3608,6 @@
*/
@Override
public void clearSslPreferences() {
- checkThread();
mWebViewCore.sendMessage(EventHub.CLEAR_SSL_PREF_TABLE);
}
@@ -3694,7 +3616,6 @@
*/
@Override
public WebBackForwardList copyBackForwardList() {
- checkThread();
return mCallbackProxy.getBackForwardList().clone();
}
@@ -3705,7 +3626,6 @@
* @param listener An implementation of FindListener
*/
public void setFindListener(FindListener listener) {
- checkThread();
mFindListener = listener;
}
@@ -3714,7 +3634,6 @@
*/
@Override
public void findNext(boolean forward) {
- checkThread();
if (0 == mNativeClass) return; // client isn't initialized
mWebViewCore.sendMessage(EventHub.FIND_NEXT, forward ? 1 : 0);
}
@@ -3727,15 +3646,11 @@
return findAllBody(find, false);
}
- /**
- * @hide
- */
public void findAllAsync(String find) {
findAllBody(find, true);
}
private int findAllBody(String find, boolean isAsync) {
- checkThread();
if (0 == mNativeClass) return 0; // client isn't initialized
mLastFind = find;
if (find == null) return 0;
@@ -3772,7 +3687,6 @@
* @return boolean True if the find dialog is shown, false otherwise.
*/
public boolean showFindDialog(String text, boolean showIme) {
- checkThread();
FindActionModeCallback callback = new FindActionModeCallback(mContext);
if (mWebView.getParent() == null || mWebView.startActionMode(callback) == null) {
// Could not start the action mode, so end Find on page
@@ -3841,12 +3755,10 @@
* @return the address, or if no address is found, return null.
*/
public static String findAddress(String addr) {
- checkThread();
return findAddress(addr, false);
}
/**
- * @hide
* Return the first substring consisting of the address of a physical
* location. Currently, only addresses in the United States are detected,
* and consist of:
@@ -3876,7 +3788,6 @@
*/
@Override
public void clearMatches() {
- checkThread();
if (mNativeClass == 0)
return;
mWebViewCore.removeMessages(EventHub.FIND_ALL);
@@ -3906,7 +3817,6 @@
*/
@Override
public void documentHasImages(Message response) {
- checkThread();
if (response == null) {
return;
}
@@ -3915,8 +3825,6 @@
/**
* Request the scroller to abort any ongoing animation
- *
- * @hide
*/
public void stopScroll() {
mScroller.forceFinished(true);
@@ -4340,7 +4248,6 @@
*/
@Override
public void setWebViewClient(WebViewClient client) {
- checkThread();
mCallbackProxy.setWebViewClient(client);
}
@@ -4348,7 +4255,7 @@
* Gets the WebViewClient
* @return the current WebViewClient instance.
*
- * @hide This is an implementation detail.
+ * This is an implementation detail.
*/
public WebViewClient getWebViewClient() {
return mCallbackProxy.getWebViewClient();
@@ -4359,7 +4266,6 @@
*/
@Override
public void setDownloadListener(DownloadListener listener) {
- checkThread();
mCallbackProxy.setDownloadListener(listener);
}
@@ -4368,7 +4274,6 @@
*/
@Override
public void setWebChromeClient(WebChromeClient client) {
- checkThread();
mCallbackProxy.setWebChromeClient(client);
}
@@ -4376,7 +4281,7 @@
* Gets the chrome handler.
* @return the current WebChromeClient instance.
*
- * @hide This is an implementation detail.
+ * This is an implementation detail.
*/
public WebChromeClient getWebChromeClient() {
return mCallbackProxy.getWebChromeClient();
@@ -4387,7 +4292,6 @@
* WebBackForwardListClient for handling new items and changes in the
* history index.
* @param client An implementation of WebBackForwardListClient.
- * {@hide}
*/
public void setWebBackForwardListClient(WebBackForwardListClient client) {
mCallbackProxy.setWebBackForwardListClient(client);
@@ -4395,7 +4299,6 @@
/**
* Gets the WebBackForwardListClient.
- * {@hide}
*/
public WebBackForwardListClient getWebBackForwardListClient() {
return mCallbackProxy.getWebBackForwardListClient();
@@ -4407,21 +4310,14 @@
@Override
@Deprecated
public void setPictureListener(PictureListener listener) {
- checkThread();
mPictureListener = listener;
}
- /**
- * {@hide}
- */
/* FIXME: Debug only! Remove for SDK! */
public void externalRepresentation(Message callback) {
mWebViewCore.sendMessage(EventHub.REQUEST_EXT_REPRESENTATION, callback);
}
- /**
- * {@hide}
- */
/* FIXME: Debug only! Remove for SDK! */
public void documentAsText(Message callback) {
mWebViewCore.sendMessage(EventHub.REQUEST_DOC_AS_TEXT, callback);
@@ -4432,7 +4328,6 @@
*/
@Override
public void addJavascriptInterface(Object object, String name) {
- checkThread();
if (object == null) {
return;
}
@@ -4447,7 +4342,6 @@
*/
@Override
public void removeJavascriptInterface(String interfaceName) {
- checkThread();
if (mWebViewCore != null) {
WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData();
arg.mInterfaceName = interfaceName;
@@ -4462,7 +4356,6 @@
*/
@Override
public WebSettingsClassic getSettings() {
- checkThread();
return (mWebViewCore != null) ? mWebViewCore.getSettings() : null;
}
@@ -4471,7 +4364,6 @@
*/
@Deprecated
public static synchronized PluginList getPluginList() {
- checkThread();
return new PluginList();
}
@@ -4480,7 +4372,6 @@
*/
@Deprecated
public void refreshPlugins(boolean reloadOpenPages) {
- checkThread();
}
//-------------------------------------------------------------------------
@@ -4784,7 +4675,7 @@
/**
* Select the word at the last click point.
*
- * @hide This is an implementation detail.
+ * This is an implementation detail.
*/
public boolean selectText() {
int x = viewToContentX(mLastTouchX + getScrollX());
@@ -5135,7 +5026,7 @@
/**
* Dump the display tree to "/sdcard/displayTree.txt"
*
- * @hide debug only
+ * debug only
*/
public void dumpDisplayTree() {
nativeDumpDisplayTree(getUrl());
@@ -5145,7 +5036,7 @@
* Dump the dom tree to adb shell if "toFile" is False, otherwise dump it to
* "/sdcard/domTree.txt"
*
- * @hide debug only
+ * debug only
*/
public void dumpDomTree(boolean toFile) {
mWebViewCore.sendMessage(EventHub.DUMP_DOMTREE, toFile ? 1 : 0, 0);
@@ -5155,7 +5046,7 @@
* Dump the render tree to adb shell if "toFile" is False, otherwise dump it
* to "/sdcard/renderTree.txt"
*
- * @hide debug only
+ * debug only
*/
public void dumpRenderTree(boolean toFile) {
mWebViewCore.sendMessage(EventHub.DUMP_RENDERTREE, toFile ? 1 : 0, 0);
@@ -5164,7 +5055,7 @@
/**
* Called by DRT on UI thread, need to proxy to WebCore thread.
*
- * @hide debug only
+ * debug only
*/
public void useMockDeviceOrientation() {
mWebViewCore.sendMessage(EventHub.USE_MOCK_DEVICE_ORIENTATION);
@@ -5173,7 +5064,7 @@
/**
* Called by DRT on WebCore thread.
*
- * @hide debug only
+ * debug only
*/
public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
@@ -5510,13 +5401,12 @@
@Override
@Deprecated
public void emulateShiftHeld() {
- checkThread();
}
/**
* Select all of the text in this WebView.
*
- * @hide This is an implementation detail.
+ * This is an implementation detail.
*/
public void selectAll() {
mWebViewCore.sendMessage(EventHub.SELECT_ALL);
@@ -5548,7 +5438,7 @@
/**
* Copy the selection to the clipboard
*
- * @hide This is an implementation detail.
+ * This is an implementation detail.
*/
public boolean copySelection() {
boolean copiedSomething = false;
@@ -5575,7 +5465,7 @@
/**
* Cut the selected text into the clipboard
*
- * @hide This is an implementation detail
+ * This is an implementation detail
*/
public void cutSelection() {
copySelection();
@@ -5587,7 +5477,7 @@
/**
* Paste text from the clipboard to the cursor position.
*
- * @hide This is an implementation detail
+ * This is an implementation detail
*/
public void pasteFromClipboard() {
ClipboardManager cm = (ClipboardManager)mContext
@@ -5603,7 +5493,7 @@
}
/**
- * @hide This is an implementation detail.
+ * This is an implementation detail.
*/
public SearchBox getSearchBox() {
if ((mWebViewCore == null) || (mWebViewCore.getBrowserFrame() == null)) {
@@ -5779,9 +5669,6 @@
mVisibleContentRect, getScale());
}
- /**
- * @hide
- */
@Override
public boolean setFrame(int left, int top, int right, int bottom) {
boolean changed = mWebViewPrivate.super_setFrame(left, top, right, bottom);
@@ -6861,7 +6748,6 @@
private DrawData mLoadedPicture;
public void setMapTrackballToArrowKeys(boolean setMap) {
- checkThread();
mMapTrackballToArrowKeys = setMap;
}
@@ -7088,7 +6974,6 @@
}
public void flingScroll(int vx, int vy) {
- checkThread();
mScroller.fling(getScrollX(), getScrollY(), vx, vy, 0, computeMaxScrollX(), 0,
computeMaxScrollY(), mOverflingDistance, mOverflingDistance);
invalidate();
@@ -7210,7 +7095,6 @@
@Override
@Deprecated
public View getZoomControls() {
- checkThread();
if (!getSettings().supportZoom()) {
Log.w(LOGTAG, "This WebView doesn't support zoom.");
return null;
@@ -7239,7 +7123,6 @@
*/
@Override
public boolean canZoomIn() {
- checkThread();
return mZoomManager.canZoomIn();
}
@@ -7248,7 +7131,6 @@
*/
@Override
public boolean canZoomOut() {
- checkThread();
return mZoomManager.canZoomOut();
}
@@ -7257,7 +7139,6 @@
*/
@Override
public boolean zoomIn() {
- checkThread();
return mZoomManager.zoomIn();
}
@@ -7266,7 +7147,6 @@
*/
@Override
public boolean zoomOut() {
- checkThread();
return mZoomManager.zoomOut();
}
@@ -7556,9 +7436,6 @@
mWebViewCore.sendMessageDelayed(EventHub.SAVE_DOCUMENT_STATE, null, 1000);
}
- /**
- * @hide
- */
public synchronized WebViewCore getWebViewCore() {
return mWebViewCore;
}
@@ -8740,7 +8617,7 @@
void onPageSwapOccurred(boolean notifyAnimationStarted);
}
- /** @hide Called by JNI when pages are swapped (only occurs with hardware
+ /** Called by JNI when pages are swapped (only occurs with hardware
* acceleration) */
protected void pageSwapCallback(boolean notifyAnimationStarted) {
mWebViewCore.resumeWebKitDraw();
@@ -9130,8 +9007,10 @@
// after the page regains focus.
mListBoxMessage = Message.obtain(null,
EventHub.SINGLE_LISTBOX_CHOICE, (int) id, 0);
- mListBoxDialog.dismiss();
- mListBoxDialog = null;
+ if (mListBoxDialog != null) {
+ mListBoxDialog.dismiss();
+ mListBoxDialog = null;
+ }
}
});
if (mSelection != -1) {
@@ -9306,7 +9185,7 @@
* view-specific zoom, scroll offset, or other changes. It does not draw
* any view-specific chrome, such as progress or URL bars.
*
- * @hide only needs to be accessible to Browser and testing
+ * only needs to be accessible to Browser and testing
*/
public void drawPage(Canvas canvas) {
calcOurContentVisibleRectF(mVisibleContentRect);
@@ -9316,7 +9195,7 @@
/**
* Enable the communication b/t the webView and VideoViewProxy
*
- * @hide only used by the Browser
+ * only used by the Browser
*/
public void setHTML5VideoViewProxy(HTML5VideoViewProxy proxy) {
mHTML5VideoViewProxy = proxy;
@@ -9326,7 +9205,7 @@
* Set the time to wait between passing touches to WebCore. See also the
* TOUCH_SENT_INTERVAL member for further discussion.
*
- * @hide This is only used by the DRT test application.
+ * This is only used by the DRT test application.
*/
public void setTouchInterval(int interval) {
mCurrentTouchInterval = interval;
@@ -9353,26 +9232,14 @@
return mViewManager;
}
- private static void checkThread() {
- if (Looper.myLooper() != Looper.getMainLooper()) {
- Throwable throwable = new Throwable(
- "Warning: A WebView method was called on thread '" +
- Thread.currentThread().getName() + "'. " +
- "All WebView methods must be called on the UI thread. " +
- "Future versions of WebView may not support use on other threads.");
- Log.w(LOGTAG, Log.getStackTraceString(throwable));
- StrictMode.onWebViewMethodCalledOnWrongThread(throwable);
- }
- }
-
- /** @hide send content invalidate */
+ /** send content invalidate */
protected void contentInvalidateAll() {
if (mWebViewCore != null && !mBlockWebkitViewMessages) {
mWebViewCore.sendMessage(EventHub.CONTENT_INVALIDATE_ALL);
}
}
- /** @hide discard all textures from tiles. Used in Profiled WebView */
+ /** discard all textures from tiles. Used in Profiled WebView */
public void discardAllTextures() {
nativeDiscardAllTextures();
}
@@ -9404,7 +9271,7 @@
/**
* Begin collecting per-tile profiling data
*
- * @hide only used by profiling tests
+ * only used by profiling tests
*/
public void tileProfilingStart() {
nativeTileProfilingStart();
@@ -9412,29 +9279,29 @@
/**
* Return per-tile profiling data
*
- * @hide only used by profiling tests
+ * only used by profiling tests
*/
public float tileProfilingStop() {
return nativeTileProfilingStop();
}
- /** @hide only used by profiling tests */
+ /** only used by profiling tests */
public void tileProfilingClear() {
nativeTileProfilingClear();
}
- /** @hide only used by profiling tests */
+ /** only used by profiling tests */
public int tileProfilingNumFrames() {
return nativeTileProfilingNumFrames();
}
- /** @hide only used by profiling tests */
+ /** only used by profiling tests */
public int tileProfilingNumTilesInFrame(int frame) {
return nativeTileProfilingNumTilesInFrame(frame);
}
- /** @hide only used by profiling tests */
+ /** only used by profiling tests */
public int tileProfilingGetInt(int frame, int tile, String key) {
return nativeTileProfilingGetInt(frame, tile, key);
}
- /** @hide only used by profiling tests */
+ /** only used by profiling tests */
public float tileProfilingGetFloat(int frame, int tile, String key) {
return nativeTileProfilingGetFloat(frame, tile, key);
}
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index e36afa3..ca5648a 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -133,6 +133,16 @@
}
/**
+ * Return the drawable used to represent the scroll thumb - the component that
+ * the user can drag back and forth indicating the current value by its position.
+ *
+ * @return The current thumb drawable
+ */
+ public Drawable getThumb() {
+ return mThumb;
+ }
+
+ /**
* @see #setThumbOffset(int)
*/
public int getThumbOffset() {
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 739bcce..0f1dab5 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1908,7 +1908,8 @@
}
/**
- * Describes how the child views are horizontally aligned. Defaults to Gravity.LEFT
+ * Set the gravity for this grid. Gravity describes how the child views
+ * are horizontally aligned. Defaults to Gravity.LEFT
*
* @param gravity the gravity to apply to this grid's children
*
@@ -1922,6 +1923,17 @@
}
/**
+ * Describes how the child views are horizontally aligned. Defaults to Gravity.LEFT
+ *
+ * @return the gravity that will be applied to this grid's children
+ *
+ * @attr ref android.R.styleable#GridView_gravity
+ */
+ public int getGravity() {
+ return mGravity;
+ }
+
+ /**
* Set the amount of horizontal (x) spacing to place between each item
* in the grid.
*
@@ -1937,6 +1949,44 @@
}
}
+ /**
+ * Returns the amount of horizontal spacing currently used between each item in the grid.
+ *
+ * <p>This is only accurate for the current layout. If {@link #setHorizontalSpacing(int)}
+ * has been called but layout is not yet complete, this method may return a stale value.
+ * To get the horizontal spacing that was explicitly requested use
+ * {@link #getRequestedHorizontalSpacing()}.</p>
+ *
+ * @return Current horizontal spacing between each item in pixels
+ *
+ * @see #setHorizontalSpacing(int)
+ * @see #getRequestedHorizontalSpacing()
+ *
+ * @attr ref android.R.styleable#GridView_horizontalSpacing
+ */
+ public int getHorizontalSpacing() {
+ return mHorizontalSpacing;
+ }
+
+ /**
+ * Returns the requested amount of horizontal spacing between each item in the grid.
+ *
+ * <p>The value returned may have been supplied during inflation as part of a style,
+ * the default GridView style, or by a call to {@link #setHorizontalSpacing(int)}.
+ * If layout is not yet complete or if GridView calculated a different horizontal spacing
+ * from what was requested, this may return a different value from
+ * {@link #getHorizontalSpacing()}.</p>
+ *
+ * @return The currently requested horizontal spacing between items, in pixels
+ *
+ * @see #setHorizontalSpacing(int)
+ * @see #getHorizontalSpacing()
+ *
+ * @attr ref android.R.styleable#GridView_horizontalSpacing
+ */
+ public int getRequestedHorizontalSpacing() {
+ return mRequestedHorizontalSpacing;
+ }
/**
* Set the amount of vertical (y) spacing to place between each item
@@ -1945,6 +1995,8 @@
* @param verticalSpacing The amount of vertical space between items,
* in pixels.
*
+ * @see #getVerticalSpacing()
+ *
* @attr ref android.R.styleable#GridView_verticalSpacing
*/
public void setVerticalSpacing(int verticalSpacing) {
@@ -1955,6 +2007,19 @@
}
/**
+ * Returns the amount of vertical spacing between each item in the grid.
+ *
+ * @return The vertical spacing between items in pixels
+ *
+ * @see #setVerticalSpacing(int)
+ *
+ * @attr ref android.R.styleable#GridView_verticalSpacing
+ */
+ public int getVerticalSpacing() {
+ return mVerticalSpacing;
+ }
+
+ /**
* Control how items are stretched to fill their space.
*
* @param stretchMode Either {@link #NO_STRETCH},
@@ -1988,6 +2053,39 @@
}
/**
+ * Return the width of a column in the grid.
+ *
+ * <p>This may not be valid yet if a layout is pending.</p>
+ *
+ * @return The column width in pixels
+ *
+ * @see #setColumnWidth(int)
+ * @see #getRequestedColumnWidth()
+ *
+ * @attr ref android.R.styleable#GridView_columnWidth
+ */
+ public int getColumnWidth() {
+ return mColumnWidth;
+ }
+
+ /**
+ * Return the requested width of a column in the grid.
+ *
+ * <p>This may not be the actual column width used. Use {@link #getColumnWidth()}
+ * to retrieve the current real width of a column.</p>
+ *
+ * @return The requested column width in pixels
+ *
+ * @see #setColumnWidth(int)
+ * @see #getColumnWidth()
+ *
+ * @attr ref android.R.styleable#GridView_columnWidth
+ */
+ public int getRequestedColumnWidth() {
+ return mRequestedColumnWidth;
+ }
+
+ /**
* Set the number of columns in the grid
*
* @param numColumns The desired number of columns.
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 0563846..af722a8 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -33,14 +33,17 @@
import android.os.Bundle;
import android.os.PatternMatcher;
import android.util.Log;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.LayoutInflater;
+import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
+import android.widget.ListView;
import android.widget.TextView;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -122,6 +125,11 @@
}
setupAlert();
+
+ ListView lv = mAlert.getListView();
+ if (lv != null) {
+ lv.setOnItemLongClickListener(new ItemLongClickListener());
+ }
}
@Override
@@ -489,5 +497,18 @@
mClearDefaultHint.setVisibility(View.GONE);
}
}
+
+ class ItemLongClickListener implements AdapterView.OnItemLongClickListener {
+
+ @Override
+ public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+ ResolveInfo ri = mAdapter.resolveInfoForPosition(position);
+ Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS")
+ .setData(Uri.fromParts("package", ri.activityInfo.packageName, null));
+ startActivity(in);
+ return true;
+ }
+
+ }
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index acc3c1c..5a7d519 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -105,6 +105,12 @@
*/
public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE;
+ /**
+ * The bit in LOCK_BIOMETRIC_WEAK_FLAGS to be used to indicate whether liveliness should
+ * be used
+ */
+ public static final int FLAG_BIOMETRIC_WEAK_LIVELINESS = 0x1;
+
private final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
private final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
@@ -878,6 +884,28 @@
}
/**
+ * Set whether biometric weak liveliness is enabled.
+ */
+ public void setBiometricWeakLivelinessEnabled(boolean enabled) {
+ long currentFlag = getLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 0L);
+ long newFlag;
+ if (enabled) {
+ newFlag = currentFlag | FLAG_BIOMETRIC_WEAK_LIVELINESS;
+ } else {
+ newFlag = currentFlag & ~FLAG_BIOMETRIC_WEAK_LIVELINESS;
+ }
+ setLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, newFlag);
+ }
+
+ /**
+ * @return Whether the biometric weak liveliness is enabled.
+ */
+ public boolean isBiometricWeakLivelinessEnabled() {
+ long currentFlag = getLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 0L);
+ return ((currentFlag & FLAG_BIOMETRIC_WEAK_LIVELINESS) != 0);
+ }
+
+ /**
* Set whether the lock pattern is enabled.
*/
public void setLockPatternEnabled(boolean enabled) {
diff --git a/core/res/res/layout/notification_intruder_content.xml b/core/res/res/layout/notification_intruder_content.xml
new file mode 100644
index 0000000..61be5f5
--- /dev/null
+++ b/core/res/res/layout/notification_intruder_content.xml
@@ -0,0 +1,69 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:background="#FF333333"
+ android:padding="4dp"
+ >
+ <ImageView android:id="@+id/icon"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:scaleType="center"
+ android:padding="4dp"
+ />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="40dp"
+ android:layout_marginLeft="40dp"
+ android:orientation="vertical"
+ >
+ <TextView android:id="@+id/title"
+ android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+ <TextView android:id="@+id/text"
+ android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginTop="-4dp"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+ </LinearLayout>
+ <LinearLayout
+ android:id="@+id/actions"
+ android:layout_width="match_parent"
+ android:layout_height="40dp"
+ android:layout_marginTop="48dp"
+ android:orientation="horizontal"
+ android:visibility="gone"
+ >
+ <ImageView
+ android:id="@+id/action0"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:visibility="gone"
+ />
+ <ImageView
+ android:id="@+id/action1"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:visibility="gone"
+ />
+ <ImageView
+ android:id="@+id/action2"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:visibility="gone"
+ />
+ </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index 7fa7658..49c8893 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -21,7 +21,7 @@
for different hardware and product builds. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- see comment in values/config.xml -->
- <integer name="config_longPressOnPowerBehavior">2</integer>
+ <integer name="config_longPressOnPowerBehavior">1</integer>
<!-- Enable lockscreen rotation -->
<bool name="config_enableLockScreenRotation">true</bool>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4d9b043a..4fde018 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -284,6 +284,10 @@
point on the move. A value of 0 means no periodic scans will be used in the framework. -->
<integer translatable="false" name="config_wifi_framework_scan_interval">300000</integer>
+ <!-- Wifi driver stop delay, in milliseconds.
+ Default value is 2 minutes. -->
+ <integer translatable="false" name="config_wifi_driver_stop_delay">120000</integer>
+
<!-- Flag indicating whether the keyguard should be bypassed when
the slider is open. This can be set or unset depending how easily
the slider can be opened (for example, in a pocket or purse). -->
@@ -304,6 +308,9 @@
<!-- If this is true, the screen will fade off. -->
<bool name="config_animateScreenLights">true</bool>
+ <!-- If this is true, key chords can be used to take a screenshot on the device. -->
+ <bool name="config_enableScreenshotChord">true</bool>
+
<!-- If true, the screen can be rotated via the accelerometer in all 4
rotations as the default behavior. -->
<bool name="config_allowAllRotations">false</bool>
@@ -628,6 +635,10 @@
cell broadcasting sms, and MMS. -->
<bool name="config_sms_capable">true</bool>
+ <!-- Enable/disable default bluetooth profiles:
+ HSP_AG, ObexObjectPush, Audio, NAP -->
+ <bool name="config_bluetooth_default_profiles">true</bool>
+
<!-- IP address of the dns server to use if nobody else suggests one -->
<string name="config_default_dns_server" translatable="false">8.8.8.8</string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ea1a70a..e1bc33b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -194,6 +194,10 @@
<java-symbol type="id" name="zoomIn" />
<java-symbol type="id" name="zoomMagnify" />
<java-symbol type="id" name="zoomOut" />
+ <java-symbol type="id" name="actions" />
+ <java-symbol type="id" name="action0" />
+ <java-symbol type="id" name="action1" />
+ <java-symbol type="id" name="action2" />
<java-symbol type="attr" name="actionModeShareDrawable" />
<java-symbol type="attr" name="alertDialogCenterButtons" />
@@ -240,6 +244,8 @@
<java-symbol type="bool" name="config_useMasterVolume" />
<java-symbol type="bool" name="config_enableWallpaperService" />
<java-symbol type="bool" name="config_sendAudioBecomingNoisy" />
+ <java-symbol type="bool" name="config_enableScreenshotChord" />
+ <java-symbol type="bool" name="config_bluetooth_default_profiles" />
<java-symbol type="integer" name="config_cursorWindowSize" />
<java-symbol type="integer" name="config_longPressOnPowerBehavior" />
@@ -251,6 +257,7 @@
<java-symbol type="integer" name="db_journal_size_limit" />
<java-symbol type="integer" name="db_wal_autocheckpoint" />
<java-symbol type="integer" name="max_action_buttons" />
+ <java-symbol type="integer" name="config_wifi_driver_stop_delay" />
<java-symbol type="color" name="tab_indicator_text_v4" />
@@ -1062,6 +1069,7 @@
<java-symbol type="layout" name="zoom_container" />
<java-symbol type="layout" name="zoom_controls" />
<java-symbol type="layout" name="zoom_magnify" />
+ <java-symbol type="layout" name="notification_intruder_content" />
<java-symbol type="anim" name="slide_in_child_bottom" />
<java-symbol type="anim" name="slide_in_right" />
diff --git a/core/tests/coretests/src/android/content/pm/AppCacheTest.java b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
index 2982816..0c31e2d 100755
--- a/core/tests/coretests/src/android/content/pm/AppCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
@@ -24,6 +24,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StatFs;
+import android.os.UserId;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
@@ -674,7 +675,7 @@
PackageDataObserver observer = new PackageDataObserver();
//wait on observer
synchronized(observer) {
- getPm().clearApplicationUserData(packageName, observer);
+ getPm().clearApplicationUserData(packageName, observer, 0 /* TODO: Other users */);
long waitTime = 0;
while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) {
observer.wait(WAIT_TIME_INCR);
@@ -717,7 +718,8 @@
File getDataDir() {
try {
- ApplicationInfo appInfo = getPm().getApplicationInfo(mContext.getPackageName(), 0);
+ ApplicationInfo appInfo = getPm().getApplicationInfo(mContext.getPackageName(), 0,
+ UserId.myUserId());
return new File(appInfo.dataDir);
} catch (RemoteException e) {
throw new RuntimeException("Pacakge manager dead", e);
@@ -746,7 +748,7 @@
@LargeTest
public void testClearApplicationUserDataNoObserver() throws Exception {
- getPm().clearApplicationUserData(mContext.getPackageName(), null);
+ getPm().clearApplicationUserData(mContext.getPackageName(), null, UserId.myUserId());
//sleep for 1 minute
Thread.sleep(60*1000);
//confirm files dont exist
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index c8bf12d..3019544 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -135,7 +135,9 @@
<li>Added feature to automatically setup JAR dependencies. Any {@code .jar} files in the
{@code /libs} folder are added to the build configuration (similar to how the Ant build
system works). Also, {@code .jar} files needed by library projects are also automatically
- added to projects that depend on those library projects.</li>
+ added to projects that depend on those library projects.
+ (<a href="http://tools.android.com/recent/dealingwithdependenciesinandroidprojects">more
+ info</a>)</li>
<li>Added a feature that allows you to run some code only in debug mode. Builds now
generate a class called {@code BuildConfig} containing a {@code DEBUG} constant that is
automatically set according to your build type. You can check the ({@code BuildConfig.DEBUG})
diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd
index bbbca81..dea0c38 100644
--- a/docs/html/sdk/tools-notes.jd
+++ b/docs/html/sdk/tools-notes.jd
@@ -128,7 +128,8 @@
automatically set according to your build type. You can check the ({@code BuildConfig.DEBUG})
constant in your code to run debug-only functions.</li>
<li>Fixed issue when a project and its libraries include the same jar file in their libs
- folder.</li>
+ folder. (<a href="http://tools.android.com/recent/dealingwithdependenciesinandroidprojects">more
+ info</a>)</li>
<li>Added support for custom views with custom attributes in libraries. Layouts using
custom attributes must use the namespace URI {@code http://schemas.android.com/apk/res-auto} instead
of the URI that includes the app package name. This URI is replaced with the app specific one at
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 6698d31..383fe71 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -575,6 +575,11 @@
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
+ if (!mLayerState.canConstantState()) {
+ throw new IllegalStateException("One or more children of this LayerDrawable does " +
+ "not have constant state; this drawable cannot be mutated.");
+ }
+ mLayerState = new LayerState(mLayerState, this, null);
final ChildDrawable[] array = mLayerState.mChildren;
final int N = mLayerState.mNum;
for (int i = 0; i < N; i++) {
@@ -694,7 +699,7 @@
return stateful;
}
- public synchronized boolean canConstantState() {
+ public boolean canConstantState() {
if (!mCheckedConstantState && mChildren != null) {
mCanConstantState = true;
final int N = mNum;
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index ad27a1e..7d5d772 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -476,8 +476,7 @@
int frameCount,
audio_policy_output_flags_t flags,
const sp<IMemory>& sharedBuffer,
- audio_io_handle_t output,
- bool enforceFrameCount);
+ audio_io_handle_t output);
void flush_l();
status_t setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount);
audio_io_handle_t getOutput_l();
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 00b8679..c3ccb56 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -24,6 +24,7 @@
#include <utils/RefBase.h>
#include <utils/KeyedVector.h>
+#include <utils/String8.h>
namespace android {
@@ -180,6 +181,8 @@
bool findData(uint32_t key, uint32_t *type,
const void **data, size_t *size) const;
+ void dumpToLog() const;
+
protected:
virtual ~MetaData();
@@ -194,6 +197,7 @@
void clear();
void setData(uint32_t type, const void *data, size_t size);
void getData(uint32_t *type, const void **data, size_t *size) const;
+ String8 asString() const;
private:
uint32_t mType;
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 392ea87..7c612ba 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -30,6 +30,7 @@
class MemoryDealer;
struct OMXCodecObserver;
struct CodecProfileLevel;
+class SkipCutBuffer;
struct OMXCodec : public MediaSource,
public MediaBufferObserver {
@@ -201,6 +202,7 @@
ReadOptions::SeekMode mSeekMode;
int64_t mTargetTimeUs;
bool mOutputPortSettingsChangedPending;
+ SkipCutBuffer *mSkipCutBuffer;
MediaBuffer *mLeftOverBuffer;
@@ -378,6 +380,7 @@
const char *mimeType, bool queryDecoders,
Vector<CodecCapabilities> *results);
+
} // namespace android
#endif // OMX_CODEC_H_
diff --git a/include/media/stagefright/SkipCutBuffer.h b/include/media/stagefright/SkipCutBuffer.h
new file mode 100644
index 0000000..5c7cd47
--- /dev/null
+++ b/include/media/stagefright/SkipCutBuffer.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SKIP_CUT_BUFFER_H_
+
+#define SKIP_CUT_BUFFER_H_
+
+#include <media/stagefright/MediaBuffer.h>
+
+namespace android {
+
+/**
+ * utility class to cut the start and end off a stream of data in MediaBuffers
+ *
+ */
+class SkipCutBuffer {
+ public:
+ // 'skip' is the number of bytes to skip from the beginning
+ // 'cut' is the number of bytes to cut from the end
+ // 'output_size' is the size in bytes of the MediaBuffers that will be used
+ SkipCutBuffer(int32_t skip, int32_t cut, int32_t output_size);
+ virtual ~SkipCutBuffer();
+
+ // Submit one MediaBuffer for skipping and cutting. This may consume all or
+ // some of the data in the buffer, or it may add data to it.
+ // After this, the caller should continue processing the buffer as usual.
+ void submit(MediaBuffer *buffer);
+ void clear();
+ size_t size(); // how many bytes are currently stored in the buffer
+
+ private:
+ void write(const char *src, size_t num);
+ size_t read(char *dst, size_t num);
+ int32_t mFrontPadding;
+ int32_t mBackPadding;
+ int32_t mWriteHead;
+ int32_t mReadHead;
+ int32_t mCapacity;
+ char* mCutBuffer;
+ DISALLOW_EVIL_CONSTRUCTORS(SkipCutBuffer);
+};
+
+} // namespace android
+
+#endif // OMX_CODEC_H_
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 38d0374..4bbb04f 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -51,7 +51,7 @@
// Set to 1 to enable native processing of View properties. 0 by default. Eventually this
// will go away and we will always use this approach for accelerated apps.
-#define USE_DISPLAY_LIST_PROPERTIES 1
+#define USE_DISPLAY_LIST_PROPERTIES 0
#define TRANSLATION 0x0001
#define ROTATION 0x0002
diff --git a/libs/rs/scriptc/rs_graphics.rsh b/libs/rs/scriptc/rs_graphics.rsh
index e3fde828..80491ee 100644
--- a/libs/rs/scriptc/rs_graphics.rsh
+++ b/libs/rs/scriptc/rs_graphics.rsh
@@ -83,88 +83,6 @@
extern void __attribute__((overloadable))
rsgBindProgramStore(rs_program_store ps);
-
-/**
- * @hide
- * Get program store depth function
- *
- * @param ps
- */
-extern rs_depth_func __attribute__((overloadable))
- rsgProgramStoreGetDepthFunc(rs_program_store ps);
-
-/**
- * @hide
- * Get program store depth mask
- *
- * @param ps
- */
-extern bool __attribute__((overloadable))
- rsgProgramStoreGetDepthMask(rs_program_store ps);
-/**
- * @hide
- * Get program store red component color mask
- *
- * @param ps
- */
-extern bool __attribute__((overloadable))
- rsgProgramStoreGetColorMaskR(rs_program_store ps);
-
-/**
- * @hide
- * Get program store green component color mask
- *
- * @param ps
- */
-extern bool __attribute__((overloadable))
- rsgProgramStoreGetColorMaskG(rs_program_store ps);
-
-/**
- * @hide
- * Get program store blur component color mask
- *
- * @param ps
- */
-extern bool __attribute__((overloadable))
- rsgProgramStoreGetColorMaskB(rs_program_store ps);
-
-/**
- * @hide
- * Get program store alpha component color mask
- *
- * @param ps
- */
-extern bool __attribute__((overloadable))
- rsgProgramStoreGetColorMaskA(rs_program_store ps);
-
-/**
- * @hide
- * Get program store blend source function
- *
- * @param ps
- */
-extern rs_blend_src_func __attribute__((overloadable))
- rsgProgramStoreGetBlendSrcFunc(rs_program_store ps);
-
-/**
- * @hide
- * Get program store blend destination function
- *
- * @param ps
- */
-extern rs_blend_dst_func __attribute__((overloadable))
- rsgProgramStoreGetBlendDstFunc(rs_program_store ps);
-
-/**
- * @hide
- * Get program store dither state
- *
- * @param ps
- */
-extern bool __attribute__((overloadable))
- rsgProgramStoreGetDitherEnabled(rs_program_store ps);
-
-
/**
* Bind a new ProgramVertex to the rendering context.
*
@@ -182,24 +100,6 @@
rsgBindProgramRaster(rs_program_raster pr);
/**
- * @hide
- * Get program raster point sprite state
- *
- * @param pr
- */
-extern bool __attribute__((overloadable))
- rsgProgramRasterGetPointSpriteEnabled(rs_program_raster pr);
-
-/**
- * @hide
- * Get program raster cull mode
- *
- * @param pr
- */
-extern rs_cull_mode __attribute__((overloadable))
- rsgProgramRasterGetCullMode(rs_program_raster pr);
-
-/**
* Bind a new Sampler object to a ProgramFragment. The sampler will
* operate on the texture bound at the matching slot.
*
@@ -209,51 +109,6 @@
rsgBindSampler(rs_program_fragment, uint slot, rs_sampler);
/**
- * @hide
- * Get sampler minification value
- *
- * @param pr
- */
-extern rs_sampler_value __attribute__((overloadable))
- rsgSamplerGetMinification(rs_sampler s);
-
-/**
- * @hide
- * Get sampler magnification value
- *
- * @param pr
- */
-extern rs_sampler_value __attribute__((overloadable))
- rsgSamplerGetMagnification(rs_sampler s);
-
-/**
- * @hide
- * Get sampler wrap S value
- *
- * @param pr
- */
-extern rs_sampler_value __attribute__((overloadable))
- rsgSamplerGetWrapS(rs_sampler s);
-
-/**
- * @hide
- * Get sampler wrap T value
- *
- * @param pr
- */
-extern rs_sampler_value __attribute__((overloadable))
- rsgSamplerGetWrapT(rs_sampler s);
-
-/**
- * @hide
- * Get sampler anisotropy
- *
- * @param pr
- */
-extern float __attribute__((overloadable))
- rsgSamplerGetAnisotropy(rs_sampler s);
-
-/**
* Bind a new Allocation object to a ProgramFragment. The
* Allocation must be a valid texture for the Program. The sampling
* of the texture will be controled by the Sampler bound at the
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 9748d3b..82dd308 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -608,16 +608,15 @@
* Adjusts the master volume for the device's audio amplifier.
* <p>
*
- * @param direction The direction to adjust the volume. One of
- * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
- * {@link #ADJUST_SAME}.
+ * @param steps The number of volume steps to adjust. A positive
+ * value will raise the volume.
* @param flags One or more flags.
* @hide
*/
- public void adjustMasterVolume(int direction, int flags) {
+ public void adjustMasterVolume(int steps, int flags) {
IAudioService service = getService();
try {
- service.adjustMasterVolume(direction, flags);
+ service.adjustMasterVolume(steps, flags);
} catch (RemoteException e) {
Log.e(TAG, "Dead object in adjustMasterVolume", e);
}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index aa60d0a..5f6a61d 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -159,6 +159,9 @@
// but to support integer based AudioManager API we translate it to 0 - 100
private static final int MAX_MASTER_VOLUME = 100;
+ // Maximum volume adjust steps allowed in a single batch call.
+ private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4;
+
/* Sound effect file names */
private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
private static final String[] SOUND_EFFECT_FILES = new String[] {
@@ -619,29 +622,19 @@
}
/** @see AudioManager#adjustMasterVolume(int) */
- public void adjustMasterVolume(int direction, int flags) {
- ensureValidDirection(direction);
+ public void adjustMasterVolume(int steps, int flags) {
+ ensureValidSteps(steps);
int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
int delta = 0;
- for (int i = 0; i < mMasterVolumeRamp.length; i += 2) {
- int testVolume = mMasterVolumeRamp[i];
- int testDelta = mMasterVolumeRamp[i + 1];
- if (direction == AudioManager.ADJUST_RAISE) {
- if (volume >= testVolume) {
- delta = testDelta;
- } else {
- break;
- }
- } else if (direction == AudioManager.ADJUST_LOWER) {
- if (volume - testDelta >= testVolume) {
- delta = -testDelta;
- } else {
- break;
- }
- }
+ int numSteps = Math.abs(steps);
+ int direction = steps > 0 ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER;
+ for (int i = 0; i < numSteps; ++i) {
+ delta = findVolumeDelta(direction, volume);
+ volume += delta;
}
-// Log.d(TAG, "adjustMasterVolume volume: " + volume + " delta: " + delta + " direction: " + direction);
- setMasterVolume(volume + delta, flags);
+
+ //Log.d(TAG, "adjustMasterVolume volume: " + volume + " steps: " + steps);
+ setMasterVolume(volume, flags);
}
/** @see AudioManager#setStreamVolume(int, int, int) */
@@ -682,6 +675,41 @@
sendVolumeUpdate(streamType, oldIndex, index, flags);
}
+ private int findVolumeDelta(int direction, int volume) {
+ int delta = 0;
+ if (direction == AudioManager.ADJUST_RAISE) {
+ if (volume == MAX_MASTER_VOLUME) {
+ return 0;
+ }
+ // This is the default value if we make it to the end
+ delta = mMasterVolumeRamp[1];
+ // If we're raising the volume move down the ramp array until we
+ // find the volume we're above and use that groups delta.
+ for (int i = mMasterVolumeRamp.length - 1; i > 1; i -= 2) {
+ if (volume >= mMasterVolumeRamp[i - 1]) {
+ delta = mMasterVolumeRamp[i];
+ break;
+ }
+ }
+ } else if (direction == AudioManager.ADJUST_LOWER){
+ if (volume == 0) {
+ return 0;
+ }
+ int length = mMasterVolumeRamp.length;
+ // This is the default value if we make it to the end
+ delta = -mMasterVolumeRamp[length - 1];
+ // If we're lowering the volume move up the ramp array until we
+ // find the volume we're below and use the group below it's delta
+ for (int i = 2; i < length; i += 2) {
+ if (volume <= mMasterVolumeRamp[i]) {
+ delta = -mMasterVolumeRamp[i - 1];
+ break;
+ }
+ }
+ }
+ return delta;
+ }
+
// UI update and Broadcast Intent
private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) {
@@ -1862,6 +1890,12 @@
}
}
+ private void ensureValidSteps(int steps) {
+ if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) {
+ throw new IllegalArgumentException("Bad volume adjust steps " + steps);
+ }
+ }
+
private void ensureValidStreamType(int streamType) {
if (streamType < 0 || streamType >= mStreamStates.length) {
throw new IllegalArgumentException("Bad stream type " + streamType);
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 21e8f29..43008d4 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -3,47 +3,26 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- AudioParameter.cpp
-LOCAL_MODULE:= libmedia_helper
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- AudioTrack.cpp \
- IAudioFlinger.cpp \
- IAudioFlingerClient.cpp \
- IAudioTrack.cpp \
- IAudioRecord.cpp \
- AudioRecord.cpp \
- AudioSystem.cpp \
- mediaplayer.cpp \
- IMediaPlayerService.cpp \
- IMediaPlayerClient.cpp \
- IMediaRecorderClient.cpp \
- IMediaPlayer.cpp \
- IMediaRecorder.cpp \
- IStreamSource.cpp \
- Metadata.cpp \
- mediarecorder.cpp \
- IMediaMetadataRetriever.cpp \
- mediametadataretriever.cpp \
- ToneGenerator.cpp \
- JetPlayer.cpp \
- IOMX.cpp \
- IAudioPolicyService.cpp \
- MediaScanner.cpp \
- MediaScannerClient.cpp \
autodetect.cpp \
IMediaDeathNotifier.cpp \
+ IMediaMetadataRetriever.cpp \
+ IMediaPlayerClient.cpp \
+ IMediaPlayer.cpp \
+ IMediaPlayerService.cpp \
+ IMediaRecorderClient.cpp \
+ IMediaRecorder.cpp \
+ IOMX.cpp \
+ IStreamSource.cpp \
+ JetPlayer.cpp \
+ mediametadataretriever.cpp \
+ mediaplayer.cpp \
MediaProfiles.cpp \
- IEffect.cpp \
- IEffectClient.cpp \
- AudioEffect.cpp \
- Visualizer.cpp \
- MemoryLeakTrackUtil.cpp
+ mediarecorder.cpp \
+ MediaScannerClient.cpp \
+ MediaScanner.cpp \
+ MemoryLeakTrackUtil.cpp \
+ Metadata.cpp \
+ Visualizer.cpp
LOCAL_SHARED_LIBRARIES := \
libui libcutils libutils libbinder libsonivox libicuuc libexpat \
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 55cd3ad..50fbf36 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -261,8 +261,7 @@
frameCount,
flags,
sharedBuffer,
- output,
- true);
+ output);
if (status != NO_ERROR) {
return status;
@@ -741,8 +740,7 @@
int frameCount,
audio_policy_output_flags_t flags,
const sp<IMemory>& sharedBuffer,
- audio_io_handle_t output,
- bool enforceFrameCount)
+ audio_io_handle_t output)
{
status_t status;
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
@@ -789,7 +787,8 @@
mNotificationFramesAct = frameCount/2;
}
if (frameCount < minFrameCount) {
- ALOGW_IF(enforceFrameCount, "Minimum buffer size corrected from %d to %d",
+ // not ALOGW because it happens all the time when playing key clicks over A2DP
+ ALOGV("Minimum buffer size corrected from %d to %d",
frameCount, minFrameCount);
frameCount = minFrameCount;
}
@@ -1249,8 +1248,7 @@
mFrameCount,
mFlags,
mSharedBuffer,
- getOutput_l(),
- false);
+ getOutput_l());
if (result == NO_ERROR) {
uint32_t user = cblk->user;
diff --git a/media/libmedia_native/Android.mk b/media/libmedia_native/Android.mk
index 065a90f..07f0978 100644
--- a/media/libmedia_native/Android.mk
+++ b/media/libmedia_native/Android.mk
@@ -1,11 +1,39 @@
-LOCAL_PATH := $(call my-dir)
+# FIXME remove "/../libmedia" at same time as rename
+LOCAL_PATH := $(call my-dir)/../libmedia
include $(CLEAR_VARS)
-LOCAL_SRC_FILES :=
+LOCAL_SRC_FILES:= \
+ AudioParameter.cpp
+LOCAL_MODULE:= libmedia_helper
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ AudioEffect.cpp \
+ AudioRecord.cpp \
+ AudioSystem.cpp \
+ AudioTrack.cpp \
+ IAudioFlingerClient.cpp \
+ IAudioFlinger.cpp \
+ IAudioPolicyService.cpp \
+ IAudioRecord.cpp \
+ IAudioTrack.cpp \
+ IEffectClient.cpp \
+ IEffect.cpp \
+ ToneGenerator.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libaudioutils libbinder libcutils libutils
LOCAL_MODULE:= libmedia_native
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, audio-utils)
+
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 148018d..840e475 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -541,6 +541,12 @@
}
static player_type getDefaultPlayerType() {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.use-nuplayer", value, NULL)
+ && (!strcmp("1", value) || !strcasecmp("true", value))) {
+ return NU_PLAYER;
+ }
+
return STAGEFRIGHT_PLAYER;
}
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 7dbb57f..776d288 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -87,6 +87,7 @@
sp<MediaMetadataRetrieverBase> p;
switch (playerType) {
case STAGEFRIGHT_PLAYER:
+ case NU_PLAYER:
{
p = new StagefrightMetadataRetriever;
break;
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
index 9b485d7..73336ef 100644
--- a/media/libmediaplayerservice/nuplayer/Android.mk
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -2,6 +2,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
+ GenericSource.cpp \
HTTPLiveSource.cpp \
NuPlayer.cpp \
NuPlayerDecoder.cpp \
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
new file mode 100644
index 0000000..99569c9
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GenericSource.h"
+
+#include "AnotherPacketSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+NuPlayer::GenericSource::GenericSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers,
+ bool uidValid,
+ uid_t uid)
+ : mDurationUs(0ll),
+ mAudioIsVorbis(false) {
+ DataSource::RegisterDefaultSniffers();
+
+ sp<DataSource> dataSource =
+ DataSource::CreateFromURI(url, headers);
+ CHECK(dataSource != NULL);
+
+ initFromDataSource(dataSource);
+}
+
+NuPlayer::GenericSource::GenericSource(
+ int fd, int64_t offset, int64_t length)
+ : mDurationUs(0ll),
+ mAudioIsVorbis(false) {
+ DataSource::RegisterDefaultSniffers();
+
+ sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
+
+ initFromDataSource(dataSource);
+}
+
+void NuPlayer::GenericSource::initFromDataSource(
+ const sp<DataSource> &dataSource) {
+ sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+
+ CHECK(extractor != NULL);
+
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ sp<MediaSource> track;
+
+ if (!strncasecmp(mime, "audio/", 6)) {
+ if (mAudioTrack.mSource == NULL) {
+ mAudioTrack.mSource = track = extractor->getTrack(i);
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
+ mAudioIsVorbis = true;
+ } else {
+ mAudioIsVorbis = false;
+ }
+ }
+ } else if (!strncasecmp(mime, "video/", 6)) {
+ if (mVideoTrack.mSource == NULL) {
+ mVideoTrack.mSource = track = extractor->getTrack(i);
+ }
+ }
+
+ if (track != NULL) {
+ int64_t durationUs;
+ if (meta->findInt64(kKeyDuration, &durationUs)) {
+ if (durationUs > mDurationUs) {
+ mDurationUs = durationUs;
+ }
+ }
+ }
+ }
+}
+
+NuPlayer::GenericSource::~GenericSource() {
+}
+
+void NuPlayer::GenericSource::start() {
+ ALOGI("start");
+
+ if (mAudioTrack.mSource != NULL) {
+ CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK);
+
+ mAudioTrack.mPackets =
+ new AnotherPacketSource(mAudioTrack.mSource->getFormat());
+
+ readBuffer(true /* audio */);
+ }
+
+ if (mVideoTrack.mSource != NULL) {
+ CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK);
+
+ mVideoTrack.mPackets =
+ new AnotherPacketSource(mVideoTrack.mSource->getFormat());
+
+ readBuffer(false /* audio */);
+ }
+}
+
+status_t NuPlayer::GenericSource::feedMoreTSData() {
+ return OK;
+}
+
+sp<MetaData> NuPlayer::GenericSource::getFormat(bool audio) {
+ sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
+
+ if (source == NULL) {
+ return NULL;
+ }
+
+ return source->getFormat();
+}
+
+status_t NuPlayer::GenericSource::dequeueAccessUnit(
+ bool audio, sp<ABuffer> *accessUnit) {
+ Track *track = audio ? &mAudioTrack : &mVideoTrack;
+
+ if (track->mSource == NULL) {
+ return -EWOULDBLOCK;
+ }
+
+ status_t finalResult;
+ if (!track->mPackets->hasBufferAvailable(&finalResult)) {
+ return finalResult == OK ? -EWOULDBLOCK : finalResult;
+ }
+
+ status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
+
+ readBuffer(audio, -1ll);
+
+ return result;
+}
+
+status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
+ *durationUs = mDurationUs;
+ return OK;
+}
+
+status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) {
+ if (mVideoTrack.mSource != NULL) {
+ int64_t actualTimeUs;
+ readBuffer(false /* audio */, seekTimeUs, &actualTimeUs);
+
+ seekTimeUs = actualTimeUs;
+ }
+
+ if (mAudioTrack.mSource != NULL) {
+ readBuffer(true /* audio */, seekTimeUs);
+ }
+
+ return OK;
+}
+
+void NuPlayer::GenericSource::readBuffer(
+ bool audio, int64_t seekTimeUs, int64_t *actualTimeUs) {
+ Track *track = audio ? &mAudioTrack : &mVideoTrack;
+ CHECK(track->mSource != NULL);
+
+ if (actualTimeUs) {
+ *actualTimeUs = seekTimeUs;
+ }
+
+ MediaSource::ReadOptions options;
+
+ bool seeking = false;
+
+ if (seekTimeUs >= 0) {
+ options.setSeekTo(seekTimeUs);
+ seeking = true;
+ }
+
+ for (;;) {
+ MediaBuffer *mbuf;
+ status_t err = track->mSource->read(&mbuf, &options);
+
+ options.clearSeekTo();
+
+ if (err == OK) {
+ size_t outLength = mbuf->range_length();
+
+ if (audio && mAudioIsVorbis) {
+ outLength += sizeof(int32_t);
+ }
+
+ sp<ABuffer> buffer = new ABuffer(outLength);
+
+ memcpy(buffer->data(),
+ (const uint8_t *)mbuf->data() + mbuf->range_offset(),
+ mbuf->range_length());
+
+ if (audio && mAudioIsVorbis) {
+ int32_t numPageSamples;
+ if (!mbuf->meta_data()->findInt32(
+ kKeyValidSamples, &numPageSamples)) {
+ numPageSamples = -1;
+ }
+
+ memcpy(buffer->data() + mbuf->range_length(),
+ &numPageSamples,
+ sizeof(numPageSamples));
+ }
+
+ int64_t timeUs;
+ CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
+
+ buffer->meta()->setInt64("timeUs", timeUs);
+
+ if (actualTimeUs) {
+ *actualTimeUs = timeUs;
+ }
+
+ mbuf->release();
+ mbuf = NULL;
+
+ if (seeking) {
+ track->mPackets->queueDiscontinuity(
+ ATSParser::DISCONTINUITY_SEEK, NULL);
+ }
+
+ track->mPackets->queueAccessUnit(buffer);
+ break;
+ } else if (err == INFO_FORMAT_CHANGED) {
+#if 0
+ track->mPackets->queueDiscontinuity(
+ ATSParser::DISCONTINUITY_FORMATCHANGE, NULL);
+#endif
+ } else {
+ track->mPackets->signalEOS(err);
+ break;
+ }
+ }
+}
+
+bool NuPlayer::GenericSource::isSeekable() {
+ return true;
+}
+
+} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
new file mode 100644
index 0000000..aaa5876
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GENERIC_SOURCE_H_
+
+#define GENERIC_SOURCE_H_
+
+#include "NuPlayer.h"
+#include "NuPlayerSource.h"
+
+#include "ATSParser.h"
+
+namespace android {
+
+struct AnotherPacketSource;
+struct ARTSPController;
+struct DataSource;
+struct MediaSource;
+
+struct NuPlayer::GenericSource : public NuPlayer::Source {
+ GenericSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers,
+ bool uidValid = false,
+ uid_t uid = 0);
+
+ GenericSource(int fd, int64_t offset, int64_t length);
+
+ virtual void start();
+
+ virtual status_t feedMoreTSData();
+
+ virtual sp<MetaData> getFormat(bool audio);
+ virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+
+ virtual status_t getDuration(int64_t *durationUs);
+ virtual status_t seekTo(int64_t seekTimeUs);
+ virtual bool isSeekable();
+
+protected:
+ virtual ~GenericSource();
+
+private:
+ struct Track {
+ sp<MediaSource> mSource;
+ sp<AnotherPacketSource> mPackets;
+ };
+
+ Track mAudioTrack;
+ Track mVideoTrack;
+
+ int64_t mDurationUs;
+ bool mAudioIsVorbis;
+
+ void initFromDataSource(const sp<DataSource> &dataSource);
+
+ void readBuffer(
+ bool audio,
+ int64_t seekTimeUs = -1ll, int64_t *actualTimeUs = NULL);
+
+ DISALLOW_EVIL_CONSTRUCTORS(GenericSource);
+};
+
+} // namespace android
+
+#endif // GENERIC_SOURCE_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 526120a..544d501 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -27,6 +27,7 @@
#include "NuPlayerSource.h"
#include "RTSPSource.h"
#include "StreamingSource.h"
+#include "GenericSource.h"
#include "ATSParser.h"
@@ -84,18 +85,44 @@
msg->post();
}
+static bool IsHTTPLiveURL(const char *url) {
+ if (!strncasecmp("http://", url, 7)
+ || !strncasecmp("https://", url, 8)) {
+ size_t len = strlen(url);
+ if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
+ return true;
+ }
+
+ if (strstr(url,"m3u8")) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void NuPlayer::setDataSource(
const char *url, const KeyedVector<String8, String8> *headers) {
sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
- if (!strncasecmp(url, "rtsp://", 7)) {
- msg->setObject(
- "source", new RTSPSource(url, headers, mUIDValid, mUID));
+ sp<Source> source;
+ if (IsHTTPLiveURL(url)) {
+ source = new HTTPLiveSource(url, headers, mUIDValid, mUID);
+ } else if (!strncasecmp(url, "rtsp://", 7)) {
+ source = new RTSPSource(url, headers, mUIDValid, mUID);
} else {
- msg->setObject(
- "source", new HTTPLiveSource(url, headers, mUIDValid, mUID));
+ source = new GenericSource(url, headers, mUIDValid, mUID);
}
+ msg->setObject("source", source);
+ msg->post();
+}
+
+void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
+ sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
+
+ sp<Source> source = new GenericSource(fd, offset, length);
+ msg->setObject("source", source);
msg->post();
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 6be14be..25766e0 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -40,6 +40,8 @@
void setDataSource(
const char *url, const KeyedVector<String8, String8> *headers);
+ void setDataSource(int fd, int64_t offset, int64_t length);
+
void setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture);
void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink);
void start();
@@ -60,12 +62,13 @@
private:
struct Decoder;
+ struct GenericSource;
struct HTTPLiveSource;
struct NuPlayerStreamListener;
struct Renderer;
+ struct RTSPSource;
struct Source;
struct StreamingSource;
- struct RTSPSource;
enum {
kWhatSetDataSource = '=DaS',
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 460fc98..1600141 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -228,6 +228,20 @@
buffer->meta()->setInt32("csd", true);
mCSD.push(buffer);
+ } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
+ sp<ABuffer> buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
+
+ CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
+
+ buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
}
return msg;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 5aa99bf..253bc2fa 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -76,7 +76,13 @@
}
status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
- return INVALID_OPERATION;
+ CHECK_EQ((int)mState, (int)UNINITIALIZED);
+
+ mPlayer->setDataSource(fd, offset, length);
+
+ mState = STOPPED;
+
+ return OK;
}
status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
@@ -97,13 +103,16 @@
}
status_t NuPlayerDriver::prepare() {
+ sendEvent(MEDIA_SET_VIDEO_SIZE, 320, 240);
return OK;
}
status_t NuPlayerDriver::prepareAsync() {
+ status_t err = prepare();
+
notifyListener(MEDIA_PREPARED);
- return OK;
+ return err;
}
status_t NuPlayerDriver::start() {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 5738ecb..ecbc428 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -376,7 +376,8 @@
bool tooLate = (mVideoLateByUs > 40000);
if (tooLate) {
- ALOGV("video late by %lld us (%.2f secs)", mVideoLateByUs, mVideoLateByUs / 1E6);
+ ALOGV("video late by %lld us (%.2f secs)",
+ mVideoLateByUs, mVideoLateByUs / 1E6);
} else {
ALOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6);
}
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 77714f3..7d7bd7d 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -42,6 +42,7 @@
OggExtractor.cpp \
SampleIterator.cpp \
SampleTable.cpp \
+ SkipCutBuffer.cpp \
StagefrightMediaScanner.cpp \
StagefrightMetadataRetriever.cpp \
SurfaceMediaSource.cpp \
diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp
index 66dec90..755594a 100644
--- a/media/libstagefright/MetaData.cpp
+++ b/media/libstagefright/MetaData.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MetaData"
+#include <utils/Log.h>
+
#include <stdlib.h>
#include <string.h>
@@ -282,5 +286,60 @@
mSize = 0;
}
+String8 MetaData::typed_data::asString() const {
+ String8 out;
+ const void *data = storage();
+ switch(mType) {
+ case TYPE_NONE:
+ out = String8::format("no type, size %d)", mSize);
+ break;
+ case TYPE_C_STRING:
+ out = String8::format("(char*) %s", (const char *)data);
+ break;
+ case TYPE_INT32:
+ out = String8::format("(int32_t) %d", *(int32_t *)data);
+ break;
+ case TYPE_INT64:
+ out = String8::format("(int64_t) %lld", *(int64_t *)data);
+ break;
+ case TYPE_FLOAT:
+ out = String8::format("(float) %f", *(float *)data);
+ break;
+ case TYPE_POINTER:
+ out = String8::format("(void*) %p", *(void **)data);
+ break;
+ case TYPE_RECT:
+ {
+ const Rect *r = (const Rect *)data;
+ out = String8::format("Rect(%d, %d, %d, %d)",
+ r->mLeft, r->mTop, r->mRight, r->mBottom);
+ break;
+ }
+
+ default:
+ out = String8::format("(unknown type %d, size %d)", mType, mSize);
+ break;
+ }
+ return out;
+}
+
+static void MakeFourCCString(uint32_t x, char *s) {
+ s[0] = x >> 24;
+ s[1] = (x >> 16) & 0xff;
+ s[2] = (x >> 8) & 0xff;
+ s[3] = x & 0xff;
+ s[4] = '\0';
+}
+
+void MetaData::dumpToLog() const {
+ for (int i = mItems.size(); --i >= 0;) {
+ int32_t key = mItems.keyAt(i);
+ char cc[5];
+ MakeFourCCString(key, cc);
+ const typed_data &item = mItems.valueAt(i);
+ ALOGI("%s: %s", cc, item.asString().string());
+ }
+}
+
} // namespace android
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index d5e6bec..8b6e9d5 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -38,6 +38,7 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/Utils.h>
+#include <media/stagefright/SkipCutBuffer.h>
#include <utils/Vector.h>
#include <OMX_Audio.h>
@@ -1303,6 +1304,7 @@
mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC),
mTargetTimeUs(-1),
mOutputPortSettingsChangedPending(false),
+ mSkipCutBuffer(NULL),
mLeftOverBuffer(NULL),
mPaused(false),
mNativeWindow(
@@ -1413,6 +1415,9 @@
free(mMIME);
mMIME = NULL;
+
+ delete mSkipCutBuffer;
+ mSkipCutBuffer = NULL;
}
status_t OMXCodec::init() {
@@ -1573,6 +1578,34 @@
portIndex == kPortIndexInput ? "input" : "output");
}
+ if (portIndex == kPortIndexOutput) {
+
+ sp<MetaData> meta = mSource->getFormat();
+ int32_t delay = 0;
+ if (!meta->findInt32(kKeyEncoderDelay, &delay)) {
+ delay = 0;
+ }
+ int32_t padding = 0;
+ if (!meta->findInt32(kKeyEncoderPadding, &padding)) {
+ padding = 0;
+ }
+ int32_t numchannels = 0;
+ if (delay + padding) {
+ if (meta->findInt32(kKeyChannelCount, &numchannels)) {
+ size_t frameSize = numchannels * sizeof(int16_t);
+ if (mSkipCutBuffer) {
+ size_t prevbuffersize = mSkipCutBuffer->size();
+ if (prevbuffersize != 0) {
+ ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbuffersize);
+ }
+ delete mSkipCutBuffer;
+ }
+ mSkipCutBuffer = new SkipCutBuffer(delay * frameSize, padding * frameSize,
+ def.nBufferSize);
+ }
+ }
+ }
+
// dumpPortStatus(portIndex);
if (portIndex == kPortIndexInput && (mFlags & kUseSecureInputBuffers)) {
@@ -2490,6 +2523,10 @@
CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
mPortBuffers[portIndex].size());
+ if (mSkipCutBuffer && mPortStatus[kPortIndexOutput] == ENABLED) {
+ mSkipCutBuffer->clear();
+ }
+
if (mState == RECONFIGURING) {
CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
@@ -3800,6 +3837,9 @@
info->mStatus = OWNED_BY_CLIENT;
info->mMediaBuffer->add_ref();
+ if (mSkipCutBuffer) {
+ mSkipCutBuffer->submit(info->mMediaBuffer);
+ }
*buffer = info->mMediaBuffer;
return OK;
diff --git a/media/libstagefright/SkipCutBuffer.cpp b/media/libstagefright/SkipCutBuffer.cpp
new file mode 100755
index 0000000..6d331b0
--- /dev/null
+++ b/media/libstagefright/SkipCutBuffer.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SkipCutBuffer"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/SkipCutBuffer.h>
+
+namespace android {
+
+SkipCutBuffer::SkipCutBuffer(int32_t skip, int32_t cut, int32_t output_size) {
+ mFrontPadding = skip;
+ mBackPadding = cut;
+ mWriteHead = 0;
+ mReadHead = 0;
+ mCapacity = cut + output_size;
+ mCutBuffer = new char[mCapacity];
+ ALOGV("skipcutbuffer %d %d %d", skip, cut, mCapacity);
+}
+
+SkipCutBuffer::~SkipCutBuffer() {
+ delete[] mCutBuffer;
+}
+
+void SkipCutBuffer::submit(MediaBuffer *buffer) {
+ int32_t offset = buffer->range_offset();
+ int32_t buflen = buffer->range_length();
+
+ // drop the initial data from the buffer if needed
+ if (mFrontPadding > 0) {
+ // still data left to drop
+ int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding;
+ offset += to_drop;
+ buflen -= to_drop;
+ buffer->set_range(offset, buflen);
+ mFrontPadding -= to_drop;
+ }
+
+
+ // append data to cutbuffer
+ char *src = ((char*) buffer->data()) + offset;
+ write(src, buflen);
+
+
+ // the mediabuffer is now empty. Fill it from cutbuffer, always leaving
+ // at least mBackPadding bytes in the cutbuffer
+ char *dst = (char*) buffer->data();
+ size_t copied = read(dst, buffer->size());
+ buffer->set_range(0, copied);
+}
+
+void SkipCutBuffer::clear() {
+ mWriteHead = mReadHead = 0;
+}
+
+void SkipCutBuffer::write(const char *src, size_t num) {
+ int32_t sizeused = (mWriteHead - mReadHead);
+ if (sizeused < 0) sizeused += mCapacity;
+
+ // everything must fit
+ CHECK_GE((mCapacity - size_t(sizeused)), num);
+
+ size_t copyfirst = (mCapacity - mWriteHead);
+ if (copyfirst > num) copyfirst = num;
+ if (copyfirst) {
+ memcpy(mCutBuffer + mWriteHead, src, copyfirst);
+ num -= copyfirst;
+ src += copyfirst;
+ mWriteHead += copyfirst;
+ CHECK_LE(mWriteHead, mCapacity);
+ if (mWriteHead == mCapacity) mWriteHead = 0;
+ if (num) {
+ memcpy(mCutBuffer, src, num);
+ mWriteHead += num;
+ }
+ }
+}
+
+size_t SkipCutBuffer::read(char *dst, size_t num) {
+ int32_t available = (mWriteHead - mReadHead);
+ if (available < 0) available += mCapacity;
+
+ available -= mBackPadding;
+ if (available <=0) {
+ return 0;
+ }
+ if (available < num) {
+ num = available;
+ }
+
+ size_t copyfirst = (mCapacity - mReadHead);
+ if (copyfirst > num) copyfirst = num;
+ if (copyfirst) {
+ memcpy(dst, mCutBuffer + mReadHead, copyfirst);
+ num -= copyfirst;
+ dst += copyfirst;
+ mReadHead += copyfirst;
+ CHECK_LE(mReadHead, mCapacity);
+ if (mReadHead == mCapacity) mReadHead = 0;
+ if (num) {
+ memcpy(dst, mCutBuffer, num);
+ mReadHead += num;
+ }
+ }
+ return available;
+}
+
+size_t SkipCutBuffer::size() {
+ int32_t available = (mWriteHead - mReadHead);
+ if (available < 0) available += mCapacity;
+ return available;
+}
+
+} // namespace android
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index ad55295..92009ee 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -115,6 +115,7 @@
mDecoderBuf = malloc(memRequirements);
pvmp3_InitDecoder(mConfig, mDecoderBuf);
+ mIsFirst = true;
}
OMX_ERRORTYPE SoftMP3::internalGetParameter(
@@ -190,7 +191,10 @@
inInfo->mOwnedByUs = false;
notifyEmptyBufferDone(inHeader);
- outHeader->nFilledLen = 0;
+ // pad the end of the stream with 529 samples, since that many samples
+ // were trimmed off the beginning when decoding started
+ outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
+ memset(outHeader->pBuffer, 0, outHeader->nFilledLen);
outHeader->nFlags = OMX_BUFFERFLAG_EOS;
outQueue.erase(outQueue.begin());
@@ -251,8 +255,17 @@
return;
}
- outHeader->nOffset = 0;
- outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t);
+ if (mIsFirst) {
+ mIsFirst = false;
+ // The decoder delay is 529 samples, so trim that many samples off
+ // the start of the first output buffer. This essentially makes this
+ // decoder have zero delay, which the rest of the pipeline assumes.
+ outHeader->nOffset = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
+ outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset;
+ } else {
+ outHeader->nOffset = 0;
+ outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t);
+ }
outHeader->nTimeStamp =
mAnchorTimeUs
@@ -288,6 +301,7 @@
// Make sure that the next buffer output does not still
// depend on fragments from the last one decoded.
pvmp3_InitDecoder(mConfig, mDecoderBuf);
+ mIsFirst = true;
}
}
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.h b/media/libstagefright/codecs/mp3dec/SoftMP3.h
index 70d0682..3a05466 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.h
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.h
@@ -46,7 +46,8 @@
private:
enum {
kNumBuffers = 4,
- kOutputBufferSize = 4608 * 2
+ kOutputBufferSize = 4608 * 2,
+ kPVMP3DecoderDelay = 529 // frames
};
tPVMP3DecoderExternal *mConfig;
@@ -57,8 +58,7 @@
int32_t mNumChannels;
int32_t mSamplingRate;
- bool mConfigured;
-
+ bool mIsFirst;
bool mSignalledError;
enum {
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 8e2294c..f69fc53 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -1145,11 +1145,15 @@
switch(error) {
case EGL11.EGL_CONTEXT_LOST:
return false;
+ case EGL10.EGL_BAD_CURRENT_SURFACE:
+ // The current surface is bad, probably because the window manager has closed
+ // the associated window. Ignore this error, on the assumption that the
+ // application will be closed soon.
+ break;
case EGL10.EGL_BAD_NATIVE_WINDOW:
- // The native window is bad, probably because the
- // window manager has closed it. Ignore this error,
- // on the expectation that the application will be closed soon.
- Log.e("EglHelper", "eglSwapBuffers returned EGL_BAD_NATIVE_WINDOW. tid=" + Thread.currentThread().getId());
+ // The native window is bad, probably because the window manager has closed it.
+ // Ignore this error, on the assumption that the application will be closed
+ // soon.
break;
default:
throwEglException("eglSwapBuffers", error);
@@ -1841,7 +1845,7 @@
! renderer.startsWith(kMSM7K_RENDERER_PREFIX);
notifyAll();
}
- mLimitedGLESContexts = !mMultipleGLESContextsAllowed || renderer.startsWith(kADRENO);
+ mLimitedGLESContexts = !mMultipleGLESContextsAllowed;
if (LOG_SURFACE) {
Log.w(TAG, "checkGLDriver renderer = \"" + renderer + "\" multipleContextsAllowed = "
+ mMultipleGLESContextsAllowed
@@ -1867,6 +1871,11 @@
}
}
+ /**
+ * This check was required for some pre-Android-3.0 hardware. Android 3.0 provides
+ * support for hardware-accelerated views, therefore multiple EGL contexts are
+ * supported on all Android 3.0+ EGL drivers.
+ */
private boolean mGLESVersionCheckComplete;
private int mGLESVersion;
private boolean mGLESDriverCheckComplete;
@@ -1875,7 +1884,6 @@
private static final int kGLES_20 = 0x20000;
private static final String kMSM7K_RENDERER_PREFIX =
"Q3Dimension MSM7500 ";
- private static final String kADRENO = "Adreno";
private GLThread mEglOwner;
}
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 090c0cb7..07f9e91 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -23,6 +23,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.os.Build;
+import android.os.UserId;
import android.util.Log;
import java.nio.Buffer;
@@ -67,7 +68,7 @@
int version = 0;
IPackageManager pm = AppGlobals.getPackageManager();
try {
- ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0);
+ ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0, UserId.myUserId());
if (applicationInfo != null) {
version = applicationInfo.targetSdkVersion;
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index a1f7316..b5dace0 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -463,6 +463,7 @@
// Screenshot trigger states
// Time to volume and power must be pressed within this interval of each other.
private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
+ private boolean mScreenshotChordEnabled;
private boolean mVolumeDownKeyTriggered;
private long mVolumeDownKeyTime;
private boolean mVolumeDownKeyConsumedByScreenshotChord;
@@ -636,7 +637,8 @@
}
private void interceptScreenshotChord() {
- if (mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
+ if (mScreenshotChordEnabled
+ && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
final long now = SystemClock.uptimeMillis();
if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
&& now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
@@ -882,6 +884,9 @@
mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_safeModeEnabledVibePattern);
+ mScreenshotChordEnabled = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableScreenshotChord);
+
// Controls rotation and the like.
initializeHdmiState();
@@ -1574,7 +1579,7 @@
// If we think we might have a volume down & power key chord on the way
// but we're not sure, then tell the dispatcher to wait a little while and
// try again later before dispatching.
- if ((flags & KeyEvent.FLAG_FALLBACK) == 0) {
+ if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
final long now = SystemClock.uptimeMillis();
final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 257f62c..69204d3 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -22,7 +22,6 @@
libcutils \
libutils \
libbinder \
- libmedia \
libmedia_native \
libhardware \
libhardware_legacy \
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 081f1f4..a85b605 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -325,9 +325,10 @@
service.onConfigurationChanged();
}
} else {
- // TODO: Verify that this only needs to be delivered for the related user and not
- // all the users
- getImplForUser().onBroadcastReceived(intent);
+ for (int i = 0; i < mAppWidgetServices.size(); i++) {
+ AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
+ service.onBroadcastReceived(intent);
+ }
}
}
};
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index 9c408c4..182a884 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.app.AlarmManager;
+import android.app.AppGlobals;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
@@ -27,6 +28,7 @@
import android.content.Intent.FilterComparison;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -158,7 +160,7 @@
Context mContext;
Locale mLocale;
- PackageManager mPackageManager;
+ IPackageManager mPm;
AlarmManager mAlarmManager;
ArrayList<Provider> mInstalledProviders = new ArrayList<Provider>();
int mNextAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID + 1;
@@ -174,7 +176,7 @@
AppWidgetServiceImpl(Context context, int userId) {
mContext = context;
- mPackageManager = context.getPackageManager();
+ mPm = AppGlobals.getPackageManager();
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mUserId = userId;
}
@@ -1009,16 +1011,19 @@
}
void loadAppWidgetList() {
- PackageManager pm = mPackageManager;
-
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
- List<ResolveInfo> broadcastReceivers = pm.queryBroadcastReceivers(intent,
- PackageManager.GET_META_DATA);
+ try {
+ List<ResolveInfo> broadcastReceivers = mPm.queryIntentReceivers(intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ PackageManager.GET_META_DATA, mUserId);
- final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
- for (int i = 0; i < N; i++) {
- ResolveInfo ri = broadcastReceivers.get(i);
- addProviderLocked(ri);
+ final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
+ for (int i = 0; i < N; i++) {
+ ResolveInfo ri = broadcastReceivers.get(i);
+ addProviderLocked(ri);
+ }
+ } catch (RemoteException re) {
+ // Shouldn't happen, local call
}
}
@@ -1131,7 +1136,7 @@
ActivityInfo activityInfo = ri.activityInfo;
XmlResourceParser parser = null;
try {
- parser = activityInfo.loadXmlMetaData(mPackageManager,
+ parser = activityInfo.loadXmlMetaData(mContext.getPackageManager(),
AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);
if (parser == null) {
Slog.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER
@@ -1159,7 +1164,7 @@
info.provider = component;
p.uid = activityInfo.applicationInfo.uid;
- Resources res = mPackageManager
+ Resources res = mContext.getPackageManager()
.getResourcesForApplication(activityInfo.applicationInfo);
TypedArray sa = res.obtainAttributes(attrs,
@@ -1188,7 +1193,7 @@
if (className != null) {
info.configure = new ComponentName(component.getPackageName(), className);
}
- info.label = activityInfo.loadLabel(mPackageManager).toString();
+ info.label = activityInfo.loadLabel(mContext.getPackageManager()).toString();
info.icon = ri.getIconResource();
info.previewImage = sa.getResourceId(
com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0);
@@ -1213,7 +1218,12 @@
}
int getUidForPackage(String packageName) throws PackageManager.NameNotFoundException {
- PackageInfo pkgInfo = mPackageManager.getPackageInfo(packageName, 0);
+ PackageInfo pkgInfo = null;
+ try {
+ pkgInfo = mPm.getPackageInfo(packageName, 0, mUserId);
+ } catch (RemoteException re) {
+ // Shouldn't happen, local call
+ }
if (pkgInfo == null || pkgInfo.applicationInfo == null) {
throw new PackageManager.NameNotFoundException();
}
@@ -1493,9 +1503,15 @@
void addProvidersForPackageLocked(String pkgName) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.setPackage(pkgName);
- List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
- PackageManager.GET_META_DATA);
-
+ List<ResolveInfo> broadcastReceivers;
+ try {
+ broadcastReceivers = mPm.queryIntentReceivers(intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ PackageManager.GET_META_DATA, mUserId);
+ } catch (RemoteException re) {
+ // Shouldn't happen, local call
+ return;
+ }
final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
for (int i = 0; i < N; i++) {
ResolveInfo ri = broadcastReceivers.get(i);
@@ -1513,8 +1529,15 @@
HashSet<String> keep = new HashSet<String>();
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.setPackage(pkgName);
- List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
- PackageManager.GET_META_DATA);
+ List<ResolveInfo> broadcastReceivers;
+ try {
+ broadcastReceivers = mPm.queryIntentReceivers(intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ PackageManager.GET_META_DATA, mUserId);
+ } catch (RemoteException re) {
+ // Shouldn't happen, local call
+ return;
+ }
// add the missing ones and collect which ones to keep
int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index b3d7220..f7e841e 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -201,7 +201,7 @@
}
public List<R> queryIntentFromList(Intent intent, String resolvedType,
- boolean defaultOnly, ArrayList<ArrayList<F>> listCut) {
+ boolean defaultOnly, ArrayList<ArrayList<F>> listCut, int userId) {
ArrayList<R> resultList = new ArrayList<R>();
final boolean debug = localLOGV ||
@@ -212,13 +212,14 @@
int N = listCut.size();
for (int i = 0; i < N; ++i) {
buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, listCut.get(i), resultList);
+ resolvedType, scheme, listCut.get(i), resultList, userId);
}
sortResults(resultList);
return resultList;
}
- public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
+ public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
+ int userId) {
String scheme = intent.getScheme();
ArrayList<R> finalList = new ArrayList<R>();
@@ -290,19 +291,19 @@
FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
if (firstTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, firstTypeCut, finalList);
+ resolvedType, scheme, firstTypeCut, finalList, userId);
}
if (secondTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, secondTypeCut, finalList);
+ resolvedType, scheme, secondTypeCut, finalList, userId);
}
if (thirdTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, thirdTypeCut, finalList);
+ resolvedType, scheme, thirdTypeCut, finalList, userId);
}
if (schemeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, schemeCut, finalList);
+ resolvedType, scheme, schemeCut, finalList, userId);
}
sortResults(finalList);
@@ -329,7 +330,7 @@
* "stopped," that is whether it should not be included in the result
* if the intent requests to excluded stopped objects.
*/
- protected boolean isFilterStopped(F filter) {
+ protected boolean isFilterStopped(F filter, int userId) {
return false;
}
@@ -341,7 +342,7 @@
protected abstract String packageForFilter(F filter);
@SuppressWarnings("unchecked")
- protected R newResult(F filter, int match) {
+ protected R newResult(F filter, int match, int userId) {
return (R)filter;
}
@@ -504,7 +505,7 @@
private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
boolean debug, boolean defaultOnly,
- String resolvedType, String scheme, List<F> src, List<R> dest) {
+ String resolvedType, String scheme, List<F> src, List<R> dest, int userId) {
final String action = intent.getAction();
final Uri data = intent.getData();
final String packageName = intent.getPackage();
@@ -519,7 +520,7 @@
int match;
if (debug) Slog.v(TAG, "Matching against filter " + filter);
- if (excludingStopped && isFilterStopped(filter)) {
+ if (excludingStopped && isFilterStopped(filter, userId)) {
if (debug) {
Slog.v(TAG, " Filter's target is stopped; skipping");
}
@@ -547,7 +548,7 @@
if (debug) Slog.v(TAG, " Filter matched! match=0x" +
Integer.toHexString(match));
if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
- final R oneResult = newResult(filter, match);
+ final R oneResult = newResult(filter, match, userId);
if (oneResult != null) {
dest.add(oneResult);
}
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 366160b..510bdb2 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -48,6 +48,7 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.UserId;
import android.os.storage.IMountService;
import android.os.storage.IMountServiceListener;
import android.os.storage.IMountShutdownObserver;
@@ -1674,7 +1675,7 @@
return false;
}
- final int packageUid = mPms.getPackageUid(packageName);
+ final int packageUid = mPms.getPackageUid(packageName, UserId.getUserId(callerUid));
if (DEBUG_OBB) {
Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java
index 326b940..a7a46dd 100644
--- a/services/java/com/android/server/WiredAccessoryObserver.java
+++ b/services/java/com/android/server/WiredAccessoryObserver.java
@@ -30,8 +30,11 @@
import android.media.AudioManager;
import android.util.Log;
+import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
/**
* <p>WiredAccessoryObserver monitors for a wired headset on the main board or dock.
@@ -39,17 +42,6 @@
class WiredAccessoryObserver extends UEventObserver {
private static final String TAG = WiredAccessoryObserver.class.getSimpleName();
private static final boolean LOG = true;
- private static final int MAX_AUDIO_PORTS = 3; /* h2w, USB Audio & hdmi */
- private static final String uEventInfo[][] = { {"DEVPATH=/devices/virtual/switch/h2w",
- "/sys/class/switch/h2w/state",
- "/sys/class/switch/h2w/name"},
- {"DEVPATH=/devices/virtual/switch/usb_audio",
- "/sys/class/switch/usb_audio/state",
- "/sys/class/switch/usb_audio/name"},
- {"DEVPATH=/devices/virtual/switch/hdmi",
- "/sys/class/switch/hdmi/state",
- "/sys/class/switch/hdmi/name"} };
-
private static final int BIT_HEADSET = (1 << 0);
private static final int BIT_HEADSET_NO_MIC = (1 << 1);
private static final int BIT_USB_HEADSET_ANLG = (1 << 2);
@@ -60,10 +52,89 @@
BIT_HDMI_AUDIO);
private static final int HEADSETS_WITH_MIC = BIT_HEADSET;
+ private static class UEventInfo {
+ private final String mDevName;
+ private final int mState1Bits;
+ private final int mState2Bits;
+
+ public UEventInfo(String devName, int state1Bits, int state2Bits) {
+ mDevName = devName;
+ mState1Bits = state1Bits;
+ mState2Bits = state2Bits;
+ }
+
+ public String getDevName() { return mDevName; }
+
+ public String getDevPath() {
+ return String.format("DEVPATH=/devices/virtual/switch/%s", mDevName);
+ }
+
+ public String getSwitchStatePath() {
+ return String.format("/sys/class/switch/%s/state", mDevName);
+ }
+
+ public boolean checkSwitchExists() {
+ File f = new File(getSwitchStatePath());
+ return ((null != f) && f.exists());
+ }
+
+ public int computeNewHeadsetState(int headsetState, int switchState) {
+ int preserveMask = ~(mState1Bits | mState2Bits);
+ int setBits = ((switchState == 1) ? mState1Bits :
+ ((switchState == 2) ? mState2Bits : 0));
+
+ return ((headsetState & preserveMask) | setBits);
+ }
+ }
+
+ private static List<UEventInfo> makeObservedUEventList() {
+ List<UEventInfo> retVal = new ArrayList<UEventInfo>();
+ UEventInfo uei;
+
+ // Monitor h2w
+ uei = new UEventInfo("h2w", BIT_HEADSET, BIT_HEADSET_NO_MIC);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ } else {
+ Slog.w(TAG, "This kernel does not have wired headset support");
+ }
+
+ // Monitor USB
+ uei = new UEventInfo("usb_audio", BIT_USB_HEADSET_ANLG, BIT_USB_HEADSET_DGTL);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ } else {
+ Slog.w(TAG, "This kernel does not have usb audio support");
+ }
+
+ // Monitor HDMI
+ //
+ // If the kernel has support for the "hdmi_audio" switch, use that. It will be signalled
+ // only when the HDMI driver has a video mode configured, and the downstream sink indicates
+ // support for audio in its EDID.
+ //
+ // If the kernel does not have an "hdmi_audio" switch, just fall back on the older "hdmi"
+ // switch instead.
+ uei = new UEventInfo("hdmi_audio", BIT_HDMI_AUDIO, 0);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ } else {
+ uei = new UEventInfo("hdmi", BIT_HDMI_AUDIO, 0);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ } else {
+ Slog.w(TAG, "This kernel does not have HDMI audio support");
+ }
+ }
+
+ return retVal;
+ }
+
+ private static List<UEventInfo> uEventInfo = makeObservedUEventList();
+
private int mHeadsetState;
private int mPrevHeadsetState;
private String mHeadsetName;
- private int switchState;
private final Context mContext;
private final WakeLock mWakeLock; // held while there is a pending route change
@@ -85,11 +156,12 @@
// one on the board, one on the dock and one on HDMI:
// observe three UEVENTs
init(); // set initial status
- for (int i = 0; i < MAX_AUDIO_PORTS; i++) {
- startObserving(uEventInfo[i][0]);
+ for (int i = 0; i < uEventInfo.size(); ++i) {
+ UEventInfo uei = uEventInfo.get(i);
+ startObserving(uei.getDevPath());
}
}
- }
+ }
@Override
public void onUEvent(UEventObserver.UEvent event) {
@@ -106,50 +178,47 @@
private synchronized final void updateState(String name, int state)
{
- if (name.equals("usb_audio")) {
- switchState = ((mHeadsetState & (BIT_HEADSET|BIT_HEADSET_NO_MIC|BIT_HDMI_AUDIO)) |
- ((state == 1) ? BIT_USB_HEADSET_ANLG :
- ((state == 2) ? BIT_USB_HEADSET_DGTL : 0)));
- } else if (name.equals("hdmi")) {
- switchState = ((mHeadsetState & (BIT_HEADSET|BIT_HEADSET_NO_MIC|
- BIT_USB_HEADSET_DGTL|BIT_USB_HEADSET_ANLG)) |
- ((state == 1) ? BIT_HDMI_AUDIO : 0));
- } else {
- switchState = ((mHeadsetState & (BIT_HDMI_AUDIO|BIT_USB_HEADSET_ANLG|
- BIT_USB_HEADSET_DGTL)) |
- ((state == 1) ? BIT_HEADSET :
- ((state == 2) ? BIT_HEADSET_NO_MIC : 0)));
+ // FIXME: When ueventd informs of a change in state for a switch, it does not have to be
+ // the case that the name reported by /sys/class/switch/<device>/name is the same as
+ // <device>. For normal users of the linux switch class driver, it will be. But it is
+ // technically possible to hook the print_name method in the class driver and return a
+ // different name each and every time the name sysfs entry is queried.
+ //
+ // Right now this is not the case for any of the switch implementations used here. I'm not
+ // certain anyone would ever choose to implement such a dynamic name, or what it would mean
+ // for the implementation at this level, but if it ever happens, we will need to revisit
+ // this code.
+ for (int i = 0; i < uEventInfo.size(); ++i) {
+ UEventInfo uei = uEventInfo.get(i);
+ if (name.equals(uei.getDevName())) {
+ update(name, uei.computeNewHeadsetState(mHeadsetState, state));
+ return;
+ }
}
- update(name, switchState);
}
private synchronized final void init() {
char[] buffer = new char[1024];
-
- String newName = mHeadsetName;
- int newState = mHeadsetState;
mPrevHeadsetState = mHeadsetState;
if (LOG) Slog.v(TAG, "init()");
- for (int i = 0; i < MAX_AUDIO_PORTS; i++) {
+ for (int i = 0; i < uEventInfo.size(); ++i) {
+ UEventInfo uei = uEventInfo.get(i);
try {
- FileReader file = new FileReader(uEventInfo[i][1]);
+ int curState;
+ FileReader file = new FileReader(uei.getSwitchStatePath());
int len = file.read(buffer, 0, 1024);
file.close();
- newState = Integer.valueOf((new String(buffer, 0, len)).trim());
+ curState = Integer.valueOf((new String(buffer, 0, len)).trim());
- file = new FileReader(uEventInfo[i][2]);
- len = file.read(buffer, 0, 1024);
- file.close();
- newName = new String(buffer, 0, len).trim();
-
- if (newState > 0) {
- updateState(newName, newState);
+ if (curState > 0) {
+ updateState(uei.getDevName(), curState);
}
} catch (FileNotFoundException e) {
- Slog.w(TAG, "This kernel does not have wired headset support");
+ Slog.w(TAG, uei.getSwitchStatePath() +
+ " not found while attempting to determine initial switch state");
} catch (Exception e) {
Slog.e(TAG, "" , e);
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d21212f..b422678 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1079,7 +1079,8 @@
int uid = msg.arg1;
boolean restart = (msg.arg2 == 1);
String pkg = (String) msg.obj;
- forceStopPackageLocked(pkg, uid, restart, false, true, false);
+ forceStopPackageLocked(pkg, uid, restart, false, true, false,
+ UserId.getUserId(uid));
}
} break;
case FINALIZE_PENDING_INTENT_MSG: {
@@ -1289,7 +1290,7 @@
ApplicationInfo info =
mSelf.mContext.getPackageManager().getApplicationInfo(
- "android", STOCK_PM_FLAGS);
+ "android", STOCK_PM_FLAGS);
mSystemThread.installSystemApplicationInfo(info);
synchronized (mSelf) {
@@ -2369,7 +2370,8 @@
List<ResolveInfo> resolves =
AppGlobals.getPackageManager().queryIntentActivities(
intent, r.resolvedType,
- PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
+ PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS,
+ UserId.getCallingUserId());
// Look for the original activity in the list...
final int N = resolves != null ? resolves.size() : 0;
@@ -3291,7 +3293,7 @@
int pkgUid = -1;
synchronized(this) {
try {
- pkgUid = pm.getPackageUid(packageName);
+ pkgUid = pm.getPackageUid(packageName, userId);
} catch (RemoteException e) {
}
if (pkgUid == -1) {
@@ -3312,7 +3314,7 @@
try {
//clear application user data
- pm.clearApplicationUserData(packageName, observer);
+ pm.clearApplicationUserData(packageName, observer, userId);
Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
Uri.fromParts("package", packageName, null));
intent.putExtra(Intent.EXTRA_UID, pkgUid);
@@ -3339,13 +3341,14 @@
throw new SecurityException(msg);
}
+ int userId = UserId.getCallingUserId();
long callingId = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
int pkgUid = -1;
synchronized(this) {
try {
- pkgUid = pm.getPackageUid(packageName);
+ pkgUid = pm.getPackageUid(packageName, userId);
} catch (RemoteException e) {
}
if (pkgUid == -1) {
@@ -3412,16 +3415,14 @@
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
- final int userId = Binder.getOrigCallingUser();
+ final int userId = UserId.getCallingUserId();
long callingId = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
int pkgUid = -1;
synchronized(this) {
try {
- pkgUid = pm.getPackageUid(packageName);
- // Convert the uid to the one for the calling user
- pkgUid = UserId.getUid(userId, pkgUid);
+ pkgUid = pm.getPackageUid(packageName, userId);
} catch (RemoteException e) {
}
if (pkgUid == -1) {
@@ -3430,7 +3431,7 @@
}
forceStopPackageLocked(packageName, pkgUid);
try {
- pm.setPackageStoppedState(packageName, true);
+ pm.setPackageStoppedState(packageName, true, userId);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -3545,7 +3546,7 @@
}
private void forceStopPackageLocked(final String packageName, int uid) {
- forceStopPackageLocked(packageName, uid, false, false, true, false);
+ forceStopPackageLocked(packageName, uid, false, false, true, false, UserId.getUserId(uid));
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
if (!mProcessesReady) {
@@ -3602,13 +3603,13 @@
private final boolean forceStopPackageLocked(String name, int uid,
boolean callerWillRestart, boolean purgeCache, boolean doit,
- boolean evenPersistent) {
+ boolean evenPersistent, int userId) {
int i;
int N;
if (uid < 0) {
try {
- uid = AppGlobals.getPackageManager().getPackageUid(name);
+ uid = AppGlobals.getPackageManager().getPackageUid(name, userId);
} catch (RemoteException e) {
}
}
@@ -3659,7 +3660,6 @@
}
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
- int userId = UserId.getUserId(uid);
for (ServiceRecord service : mServiceMap.getAllServices(userId)) {
if (service.packageName.equals(name)
&& (service.app == null || evenPersistent || !service.app.persistent)) {
@@ -4107,11 +4107,11 @@
if (pkgs != null) {
for (String pkg : pkgs) {
synchronized (ActivityManagerService.this) {
- if (forceStopPackageLocked(pkg, -1, false, false, false, false)) {
- setResultCode(Activity.RESULT_OK);
- return;
- }
- }
+ if (forceStopPackageLocked(pkg, -1, false, false, false, false, 0)) {
+ setResultCode(Activity.RESULT_OK);
+ return;
+ }
+ }
}
}
}
@@ -4290,8 +4290,8 @@
try {
if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
int uid = AppGlobals.getPackageManager()
- .getPackageUid(packageName);
- if (UserId.getAppId(callingUid) != uid) {
+ .getPackageUid(packageName, UserId.getUserId(callingUid));
+ if (!UserId.isSameApp(callingUid, uid)) {
String msg = "Permission Denial: getIntentSender() from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
@@ -4386,7 +4386,7 @@
PendingIntentRecord rec = (PendingIntentRecord)sender;
try {
int uid = AppGlobals.getPackageManager()
- .getPackageUid(rec.key.packageName);
+ .getPackageUid(rec.key.packageName, UserId.getCallingUserId());
if (!UserId.isSameApp(uid, Binder.getCallingUid())) {
String msg = "Permission Denial: cancelIntentSender() from pid="
+ Binder.getCallingPid()
@@ -4796,7 +4796,7 @@
} else {
try {
pi = pm.resolveContentProvider(name,
- PackageManager.GET_URI_PERMISSION_PATTERNS);
+ PackageManager.GET_URI_PERMISSION_PATTERNS, UserId.getUserId(callingUid));
} catch (RemoteException ex) {
}
}
@@ -4808,7 +4808,7 @@
int targetUid = lastTargetUid;
if (targetUid < 0 && targetPkg != null) {
try {
- targetUid = pm.getPackageUid(targetPkg);
+ targetUid = pm.getPackageUid(targetPkg, UserId.getUserId(callingUid));
if (targetUid < 0) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"Can't grant URI permission no uid for: " + targetPkg);
@@ -5100,14 +5100,14 @@
final String authority = uri.getAuthority();
ProviderInfo pi = null;
- ContentProviderRecord cpr = mProviderMap.getProviderByName(authority,
- UserId.getUserId(callingUid));
+ int userId = UserId.getUserId(callingUid);
+ ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userId);
if (cpr != null) {
pi = cpr.info;
} else {
try {
pi = pm.resolveContentProvider(authority,
- PackageManager.GET_URI_PERMISSION_PATTERNS);
+ PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
} catch (RemoteException ex) {
}
}
@@ -5202,7 +5202,7 @@
} else {
try {
pi = pm.resolveContentProvider(authority,
- PackageManager.GET_URI_PERMISSION_PATTERNS);
+ PackageManager.GET_URI_PERMISSION_PATTERNS, r.userId);
} catch (RemoteException ex) {
}
}
@@ -5480,12 +5480,13 @@
// Check whether this activity is currently available.
try {
if (rti.origActivity != null) {
- if (pm.getActivityInfo(rti.origActivity, 0) == null) {
+ if (pm.getActivityInfo(rti.origActivity, 0, callingUserId)
+ == null) {
continue;
}
} else if (rti.baseIntent != null) {
if (pm.queryIntentActivities(rti.baseIntent,
- null, 0) == null) {
+ null, 0, callingUserId) == null) {
continue;
}
}
@@ -6132,15 +6133,14 @@
try {
cpi = AppGlobals.getPackageManager().
resolveContentProvider(name,
- STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
+ STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
} catch (RemoteException ex) {
}
if (cpi == null) {
return null;
}
- cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo,
- Binder.getOrigCallingUser());
+ cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
String msg;
if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
@@ -6157,7 +6157,7 @@
}
ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
- cpr = mProviderMap.getProviderByClass(comp, Binder.getOrigCallingUser());
+ cpr = mProviderMap.getProviderByClass(comp, userId);
final boolean firstClass = cpr == null;
if (firstClass) {
try {
@@ -6165,13 +6165,13 @@
AppGlobals.getPackageManager().
getApplicationInfo(
cpi.applicationInfo.packageName,
- STOCK_PM_FLAGS);
+ STOCK_PM_FLAGS, userId);
if (ai == null) {
Slog.w(TAG, "No package info for content provider "
+ cpi.name);
return null;
}
- ai = getAppInfoForUser(ai, Binder.getOrigCallingUser());
+ ai = getAppInfoForUser(ai, userId);
cpr = new ContentProviderRecord(this, cpi, ai, comp);
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
@@ -6212,7 +6212,7 @@
// Content provider is now in use, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
- cpr.appInfo.packageName, false);
+ cpr.appInfo.packageName, false, userId);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -6546,7 +6546,7 @@
// This package really, really can not be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
- info.packageName, false);
+ info.packageName, false, UserId.getUserId(app.uid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -6778,7 +6778,7 @@
mDebugTransient = !persistent;
if (packageName != null) {
final long origId = Binder.clearCallingIdentity();
- forceStopPackageLocked(packageName, -1, false, false, true, true);
+ forceStopPackageLocked(packageName, -1, false, false, true, true, 0);
Binder.restoreCallingIdentity(origId);
}
}
@@ -7137,7 +7137,7 @@
List<ResolveInfo> ris = null;
try {
ris = AppGlobals.getPackageManager().queryIntentReceivers(
- intent, null, 0);
+ intent, null, 0, 0);
} catch (RemoteException e) {
}
if (ris != null) {
@@ -7394,6 +7394,10 @@
}
private boolean handleAppCrashLocked(ProcessRecord app) {
+ if (mHeadless) {
+ Log.e(TAG, "handleAppCrashLocked: " + app.processName);
+ return false;
+ }
long now = SystemClock.uptimeMillis();
Long crashTime;
@@ -7441,7 +7445,7 @@
mMainStack.resumeTopActivityLocked(null);
} else {
ActivityRecord r = mMainStack.topRunningActivityLocked(null);
- if (r.app == app) {
+ if (r != null && r.app == app) {
// If the top running activity is from this crashing
// process, then terminate it to avoid getting in a loop.
Slog.w(TAG, " Force finishing activity "
@@ -7803,7 +7807,7 @@
for (String pkg : process.pkgList) {
sb.append("Package: ").append(pkg);
try {
- PackageInfo pi = pm.getPackageInfo(pkg, 0);
+ PackageInfo pi = pm.getPackageInfo(pkg, 0, 0);
if (pi != null) {
sb.append(" v").append(pi.versionCode);
if (pi.versionName != null) {
@@ -8201,7 +8205,7 @@
IPackageManager pm = AppGlobals.getPackageManager();
for (String pkg : extList) {
try {
- ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
+ ApplicationInfo info = pm.getApplicationInfo(pkg, 0, UserId.getCallingUserId());
if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
retList.add(info);
}
@@ -10682,21 +10686,21 @@
};
private ServiceLookupResult findServiceLocked(Intent service,
- String resolvedType) {
+ String resolvedType, int userId) {
ServiceRecord r = null;
if (service.getComponent() != null) {
- r = mServiceMap.getServiceByName(service.getComponent(), Binder.getOrigCallingUser());
+ r = mServiceMap.getServiceByName(service.getComponent(), userId);
}
if (r == null) {
Intent.FilterComparison filter = new Intent.FilterComparison(service);
- r = mServiceMap.getServiceByIntent(filter, Binder.getOrigCallingUser());
+ r = mServiceMap.getServiceByIntent(filter, userId);
}
if (r == null) {
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveService(
- service, resolvedType, 0);
+ service, resolvedType, 0, userId);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
@@ -10767,7 +10771,7 @@
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveService(
- service, resolvedType, STOCK_PM_FLAGS);
+ service, resolvedType, STOCK_PM_FLAGS, userId);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
@@ -11132,7 +11136,7 @@
// Service is now being launched, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
- r.packageName, false);
+ r.packageName, false, r.userId);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -11437,7 +11441,8 @@
}
// If this service is active, make sure it is stopped.
- ServiceLookupResult r = findServiceLocked(service, resolvedType);
+ ServiceLookupResult r = findServiceLocked(service, resolvedType,
+ callerApp == null ? UserId.getCallingUserId() : callerApp.userId);
if (r != null) {
if (r.record != null) {
final long origId = Binder.clearCallingIdentity();
@@ -11465,7 +11470,8 @@
IBinder ret = null;
synchronized(this) {
- ServiceLookupResult r = findServiceLocked(service, resolvedType);
+ ServiceLookupResult r = findServiceLocked(service, resolvedType,
+ UserId.getCallingUserId());
if (r != null) {
// r.record is null if findServiceLocked() failed the caller permission check
@@ -12094,7 +12100,7 @@
// Backup agent is now in use, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
- app.packageName, false);
+ app.packageName, false, UserId.getUserId(app.uid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -12458,7 +12464,7 @@
String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
if (list != null && (list.length > 0)) {
for (String pkg : list) {
- forceStopPackageLocked(pkg, -1, false, true, true, false);
+ forceStopPackageLocked(pkg, -1, false, true, true, false, userId);
}
sendPackageBroadcastLocked(
IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
@@ -12469,7 +12475,8 @@
if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
forceStopPackageLocked(ssp,
- intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true, false);
+ intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true,
+ false, userId);
}
if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
@@ -12586,7 +12593,7 @@
if (intent.getComponent() != null) {
// Broadcast is going to one specific receiver class...
ActivityInfo ai = AppGlobals.getPackageManager().
- getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
+ getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS, userId);
if (ai != null) {
receivers = new ArrayList();
ResolveInfo ri = new ResolveInfo();
@@ -12594,15 +12601,15 @@
receivers.add(ri);
}
} else {
- // TODO: Apply userId
// Need to resolve the intent to interested receivers...
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
receivers =
AppGlobals.getPackageManager().queryIntentReceivers(
- intent, resolvedType, STOCK_PM_FLAGS);
+ intent, resolvedType, STOCK_PM_FLAGS, userId);
}
- registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
+ registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false,
+ userId);
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
@@ -12893,7 +12900,7 @@
ii = mContext.getPackageManager().getInstrumentationInfo(
className, STOCK_PM_FLAGS);
ai = mContext.getPackageManager().getApplicationInfo(
- ii.targetPackage, STOCK_PM_FLAGS);
+ ii.targetPackage, STOCK_PM_FLAGS);
} catch (PackageManager.NameNotFoundException e) {
}
if (ii == null) {
@@ -12921,9 +12928,10 @@
throw new SecurityException(msg);
}
+ int userId = UserId.getCallingUserId();
final long origId = Binder.clearCallingIdentity();
// Instrumentation can kill and relaunch even persistent processes
- forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true);
+ forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, userId);
ProcessRecord app = addAppLocked(ai, false);
app.instrumentationClass = className;
app.instrumentationInfo = ai;
@@ -12978,11 +12986,12 @@
app.instrumentationProfileFile = null;
app.instrumentationArguments = null;
- forceStopPackageLocked(app.processName, -1, false, false, true, true);
+ forceStopPackageLocked(app.processName, -1, false, false, true, true, app.userId);
}
public void finishInstrumentation(IApplicationThread target,
int resultCode, Bundle results) {
+ int userId = UserId.getCallingUserId();
// Refuse possible leaked file descriptors
if (results != null && results.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 7e8df35..48b4f4ff 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1445,9 +1445,8 @@
// Launching this app's activity, make sure the app is no longer
// considered stopped.
try {
- // TODO: Apply to the correct userId
AppGlobals.getPackageManager().setPackageStoppedState(
- next.packageName, false);
+ next.packageName, false, next.userId); /* TODO: Verify if correct userid */
} catch (RemoteException e1) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -2847,7 +2846,7 @@
}
ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
- String profileFile, ParcelFileDescriptor profileFd) {
+ String profileFile, ParcelFileDescriptor profileFd, int userId) {
// Collect information about the target of the Intent.
ActivityInfo aInfo;
try {
@@ -2855,7 +2854,7 @@
AppGlobals.getPackageManager().resolveIntent(
intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY
- | ActivityManagerService.STOCK_PM_FLAGS);
+ | ActivityManagerService.STOCK_PM_FLAGS, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
} catch (RemoteException e) {
aInfo = null;
@@ -2909,7 +2908,7 @@
// Collect information about the target of the Intent.
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
- profileFile, profileFd);
+ profileFile, profileFd, userId);
aInfo = mService.getActivityInfoForUser(aInfo, userId);
synchronized (mService) {
@@ -2989,7 +2988,7 @@
AppGlobals.getPackageManager().resolveIntent(
intent, null,
PackageManager.MATCH_DEFAULT_ONLY
- | ActivityManagerService.STOCK_PM_FLAGS);
+ | ActivityManagerService.STOCK_PM_FLAGS, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
aInfo = mService.getActivityInfoForUser(aInfo, userId);
} catch (RemoteException e) {
@@ -3098,7 +3097,7 @@
// Collect information about the target of the Intent.
ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
- 0, null, null);
+ 0, null, null, userId);
// TODO: New, check if this is correct
aInfo = mService.getActivityInfoForUser(aInfo, userId);
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index 39b63db..1b83e0b 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -732,7 +732,7 @@
// Broadcast is being executed, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
- r.curComponent.getPackageName(), false);
+ r.curComponent.getPackageName(), false, UserId.getUserId(r.callingUid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java
index cd72202..3ba3fbb 100644
--- a/services/java/com/android/server/am/CompatModePackages.java
+++ b/services/java/com/android/server/am/CompatModePackages.java
@@ -121,7 +121,7 @@
public void handlePackageAddedLocked(String packageName, boolean updated) {
ApplicationInfo ai = null;
try {
- ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
+ ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0, 0);
} catch (RemoteException e) {
}
if (ai == null) {
@@ -220,7 +220,7 @@
public int getPackageScreenCompatModeLocked(String packageName) {
ApplicationInfo ai = null;
try {
- ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
+ ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0, 0);
} catch (RemoteException e) {
}
if (ai == null) {
@@ -232,7 +232,7 @@
public void setPackageScreenCompatModeLocked(String packageName, int mode) {
ApplicationInfo ai = null;
try {
- ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
+ ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0, 0);
} catch (RemoteException e) {
}
if (ai == null) {
@@ -365,7 +365,7 @@
}
ApplicationInfo ai = null;
try {
- ai = pm.getApplicationInfo(pkg, 0);
+ ai = pm.getApplicationInfo(pkg, 0, 0);
} catch (RemoteException e) {
}
if (ai == null) {
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 0e04d59..1f1e720 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -41,7 +41,6 @@
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkPolicyManager.dumpPolicy;
import static android.net.NetworkPolicyManager.dumpRules;
-import static android.net.NetworkPolicyManager.isUidValidForPolicy;
import static android.net.NetworkTemplate.MATCH_ETHERNET;
import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
@@ -74,6 +73,7 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
@@ -96,6 +96,7 @@
import android.os.MessageQueue.IdleHandler;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.UserId;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.format.Formatter;
@@ -158,6 +159,7 @@
private static final int VERSION_SPLIT_SNOOZE = 5;
private static final int VERSION_ADDED_TIMEZONE = 6;
private static final int VERSION_ADDED_INFERRED = 7;
+ private static final int VERSION_SWITCH_APP_ID = 8;
// @VisibleForTesting
public static final int TYPE_WARNING = 0x1;
@@ -167,6 +169,7 @@
private static final String TAG_POLICY_LIST = "policy-list";
private static final String TAG_NETWORK_POLICY = "network-policy";
private static final String TAG_UID_POLICY = "uid-policy";
+ private static final String TAG_APP_POLICY = "app-policy";
private static final String ATTR_VERSION = "version";
private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
@@ -182,6 +185,7 @@
private static final String ATTR_METERED = "metered";
private static final String ATTR_INFERRED = "inferred";
private static final String ATTR_UID = "uid";
+ private static final String ATTR_APP_ID = "appId";
private static final String ATTR_POLICY = "policy";
private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground";
@@ -223,8 +227,8 @@
/** Currently active network rules for ifaces. */
private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap();
- /** Defined UID policies. */
- private SparseIntArray mUidPolicy = new SparseIntArray();
+ /** Defined app policies. */
+ private SparseIntArray mAppPolicy = new SparseIntArray();
/** Currently derived rules for each UID. */
private SparseIntArray mUidRules = new SparseIntArray();
@@ -379,18 +383,26 @@
final String action = intent.getAction();
final int uid = intent.getIntExtra(EXTRA_UID, 0);
+ final int appId = UserId.getAppId(uid);
synchronized (mRulesLock) {
if (ACTION_PACKAGE_ADDED.equals(action)) {
+ // NOTE: PACKAGE_ADDED is currently only sent once, and is
+ // not broadcast when users are added.
+
// update rules for UID, since it might be subject to
// global background data policy.
if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
- updateRulesForUidLocked(uid);
+ updateRulesForAppLocked(appId);
} else if (ACTION_UID_REMOVED.equals(action)) {
+ // NOTE: UID_REMOVED is currently only sent once, and is not
+ // broadcast when users are removed.
+
// remove any policy and update rules to clean up.
if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
- mUidPolicy.delete(uid);
- updateRulesForUidLocked(uid);
+
+ mAppPolicy.delete(appId);
+ updateRulesForAppLocked(appId);
writePolicyLocked();
}
}
@@ -949,7 +961,7 @@
// clear any existing policy and read from disk
mNetworkPolicy.clear();
- mUidPolicy.clear();
+ mAppPolicy.clear();
FileInputStream fis = null;
try {
@@ -1028,11 +1040,21 @@
final int uid = readIntAttribute(in, ATTR_UID);
final int policy = readIntAttribute(in, ATTR_POLICY);
- if (isUidValidForPolicy(mContext, uid)) {
- setUidPolicyUnchecked(uid, policy, false);
+ final int appId = UserId.getAppId(uid);
+ if (UserId.isApp(appId)) {
+ setAppPolicyUnchecked(appId, policy, false);
} else {
Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
}
+ } else if (TAG_APP_POLICY.equals(tag)) {
+ final int appId = readIntAttribute(in, ATTR_APP_ID);
+ final int policy = readIntAttribute(in, ATTR_POLICY);
+
+ if (UserId.isApp(appId)) {
+ setAppPolicyUnchecked(appId, policy, false);
+ } else {
+ Slog.w(TAG, "unable to apply policy to appId " + appId + "; ignoring");
+ }
}
}
}
@@ -1077,7 +1099,7 @@
out.startDocument(null, true);
out.startTag(null, TAG_POLICY_LIST);
- writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_INFERRED);
+ writeIntAttribute(out, ATTR_VERSION, VERSION_SWITCH_APP_ID);
writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
// write all known network policies
@@ -1102,17 +1124,17 @@
}
// write all known uid policies
- for (int i = 0; i < mUidPolicy.size(); i++) {
- final int uid = mUidPolicy.keyAt(i);
- final int policy = mUidPolicy.valueAt(i);
+ for (int i = 0; i < mAppPolicy.size(); i++) {
+ final int appId = mAppPolicy.keyAt(i);
+ final int policy = mAppPolicy.valueAt(i);
// skip writing empty policies
if (policy == POLICY_NONE) continue;
- out.startTag(null, TAG_UID_POLICY);
- writeIntAttribute(out, ATTR_UID, uid);
+ out.startTag(null, TAG_APP_POLICY);
+ writeIntAttribute(out, ATTR_APP_ID, appId);
writeIntAttribute(out, ATTR_POLICY, policy);
- out.endTag(null, TAG_UID_POLICY);
+ out.endTag(null, TAG_APP_POLICY);
}
out.endTag(null, TAG_POLICY_LIST);
@@ -1127,24 +1149,24 @@
}
@Override
- public void setUidPolicy(int uid, int policy) {
+ public void setAppPolicy(int appId, int policy) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
- if (!isUidValidForPolicy(mContext, uid)) {
- throw new IllegalArgumentException("cannot apply policy to UID " + uid);
+ if (!UserId.isApp(appId)) {
+ throw new IllegalArgumentException("cannot apply policy to appId " + appId);
}
- setUidPolicyUnchecked(uid, policy, true);
+ setAppPolicyUnchecked(appId, policy, true);
}
- private void setUidPolicyUnchecked(int uid, int policy, boolean persist) {
+ private void setAppPolicyUnchecked(int appId, int policy, boolean persist) {
final int oldPolicy;
synchronized (mRulesLock) {
- oldPolicy = getUidPolicy(uid);
- mUidPolicy.put(uid, policy);
+ oldPolicy = getAppPolicy(appId);
+ mAppPolicy.put(appId, policy);
// uid policy changed, recompute rules and persist policy.
- updateRulesForUidLocked(uid);
+ updateRulesForAppLocked(appId);
if (persist) {
writePolicyLocked();
}
@@ -1152,11 +1174,11 @@
}
@Override
- public int getUidPolicy(int uid) {
+ public int getAppPolicy(int appId) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
synchronized (mRulesLock) {
- return mUidPolicy.get(uid, POLICY_NONE);
+ return mAppPolicy.get(appId, POLICY_NONE);
}
}
@@ -1347,27 +1369,29 @@
fout.print(" "); fout.println(policy.toString());
}
- fout.println("Policy status for known UIDs:");
+ fout.println("Policy for apps:");
+ int size = mAppPolicy.size();
+ for (int i = 0; i < size; i++) {
+ final int appId = mAppPolicy.keyAt(i);
+ final int policy = mAppPolicy.valueAt(i);
+ fout.print(" appId=");
+ fout.print(appId);
+ fout.print(" policy=");
+ dumpPolicy(fout, policy);
+ fout.println();
+ }
final SparseBooleanArray knownUids = new SparseBooleanArray();
- collectKeys(mUidPolicy, knownUids);
collectKeys(mUidForeground, knownUids);
collectKeys(mUidRules, knownUids);
- final int size = knownUids.size();
+ fout.println("Status for known UIDs:");
+ size = knownUids.size();
for (int i = 0; i < size; i++) {
final int uid = knownUids.keyAt(i);
fout.print(" UID=");
fout.print(uid);
- fout.print(" policy=");
- final int policyIndex = mUidPolicy.indexOfKey(uid);
- if (policyIndex < 0) {
- fout.print("UNKNOWN");
- } else {
- dumpPolicy(fout, mUidPolicy.valueAt(policyIndex));
- }
-
fout.print(" foreground=");
final int foregroundIndex = mUidPidForeground.indexOfKey(uid);
if (foregroundIndex < 0) {
@@ -1457,7 +1481,8 @@
final PackageManager pm = mContext.getPackageManager();
final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
for (ApplicationInfo app : apps) {
- updateRulesForUidLocked(app.uid);
+ final int appId = UserId.getAppId(app.uid);
+ updateRulesForAppLocked(appId);
}
// and catch system UIDs
@@ -1476,13 +1501,21 @@
}
}
+ private void updateRulesForAppLocked(int appId) {
+ for (UserInfo user : mContext.getPackageManager().getUsers()) {
+ final int uid = UserId.getUid(user.id, appId);
+ updateRulesForUidLocked(uid);
+ }
+ }
+
private void updateRulesForUidLocked(int uid) {
- final int uidPolicy = getUidPolicy(uid);
+ final int appId = UserId.getAppId(uid);
+ final int appPolicy = getAppPolicy(appId);
final boolean uidForeground = isUidForeground(uid);
// derive active rules based on policy and active state
int uidRules = RULE_ALLOW_ALL;
- if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
+ if (!uidForeground && (appPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
// uid in background, and policy says to block metered data
uidRules = RULE_REJECT_METERED;
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index bc98f86..95666c0 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -395,7 +395,7 @@
static final int MCS_GIVE_UP = 11;
static final int UPDATED_MEDIA_STATUS = 12;
static final int WRITE_SETTINGS = 13;
- static final int WRITE_STOPPED_PACKAGES = 14;
+ static final int WRITE_PACKAGE_RESTRICTIONS = 14;
static final int PACKAGE_VERIFIED = 15;
static final int CHECK_PENDING_VERIFICATION = 16;
@@ -406,6 +406,9 @@
final UserManager mUserManager;
+ // Stores a list of users whose package restrictions file needs to be updated
+ private HashSet<Integer> mDirtyUsers = new HashSet<Integer>();
+
final private DefaultContainerConnection mDefContainerConn =
new DefaultContainerConnection();
class DefaultContainerConnection implements ServiceConnection {
@@ -629,7 +632,7 @@
packages[i] = ent.getKey();
components[i] = ent.getValue();
PackageSetting ps = mSettings.mPackages.get(ent.getKey());
- uids[i] = (ps != null) ? ps.userId : -1;
+ uids[i] = (ps != null) ? ps.uid : -1;
i++;
}
size = i;
@@ -735,16 +738,20 @@
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
synchronized (mPackages) {
removeMessages(WRITE_SETTINGS);
- removeMessages(WRITE_STOPPED_PACKAGES);
+ removeMessages(WRITE_PACKAGE_RESTRICTIONS);
mSettings.writeLPr();
+ mDirtyUsers.clear();
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
} break;
- case WRITE_STOPPED_PACKAGES: {
+ case WRITE_PACKAGE_RESTRICTIONS: {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
synchronized (mPackages) {
- removeMessages(WRITE_STOPPED_PACKAGES);
- mSettings.writeStoppedLPr();
+ removeMessages(WRITE_PACKAGE_RESTRICTIONS);
+ for (int userId : mDirtyUsers) {
+ mSettings.writePackageRestrictionsLPr(userId);
+ }
+ mDirtyUsers.clear();
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
} break;
@@ -811,10 +818,11 @@
mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
}
}
-
- void scheduleWriteStoppedPackagesLocked() {
- if (!mHandler.hasMessages(WRITE_STOPPED_PACKAGES)) {
- mHandler.sendEmptyMessageDelayed(WRITE_STOPPED_PACKAGES, WRITE_SETTINGS_DELAY);
+
+ void scheduleWritePackageRestrictionsLocked(int userId) {
+ mDirtyUsers.add(userId);
+ if (!mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
+ mHandler.sendEmptyMessageDelayed(WRITE_PACKAGE_RESTRICTIONS, WRITE_SETTINGS_DELAY);
}
}
@@ -916,7 +924,7 @@
readPermissions();
- mRestoredSettings = mSettings.readLPw();
+ mRestoredSettings = mSettings.readLPw(getUsers());
long startTime = SystemClock.uptimeMillis();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
@@ -1180,7 +1188,7 @@
private String getRequiredVerifierLPr() {
final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
- PackageManager.GET_DISABLED_COMPONENTS);
+ PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
String requiredVerifier = null;
@@ -1512,7 +1520,8 @@
ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions);
}
- public PackageInfo getPackageInfo(String packageName, int flags) {
+ @Override
+ public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
// reader
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
@@ -1522,7 +1531,7 @@
return generatePackageInfo(p, flags);
}
if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
- return generatePackageInfoFromSettingsLPw(packageName, flags);
+ return generatePackageInfoFromSettingsLPw(packageName, flags, userId);
}
}
return null;
@@ -1551,20 +1560,21 @@
}
return out;
}
-
- public int getPackageUid(String packageName) {
+
+ @Override
+ public int getPackageUid(String packageName, int userId) {
// reader
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
if(p != null) {
- return p.applicationInfo.uid;
+ return UserId.getUid(userId, p.applicationInfo.uid);
}
PackageSetting ps = mSettings.mPackages.get(packageName);
if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
return -1;
}
p = ps.pkg;
- return p != null ? p.applicationInfo.uid : -1;
+ return p != null ? UserId.getUid(userId, p.applicationInfo.uid) : -1;
}
}
@@ -1652,11 +1662,12 @@
}
}
- private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags) {
+ private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
+ int userId) {
PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
if (ps.pkg == null) {
- PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags);
+ PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags, userId);
if (pInfo != null) {
return pInfo.applicationInfo;
}
@@ -1667,7 +1678,8 @@
return null;
}
- private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags) {
+ private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags,
+ int userId) {
PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
if (ps.pkg == null) {
@@ -1679,15 +1691,16 @@
ps.pkg.applicationInfo.dataDir =
getDataPathForPackage(ps.pkg.packageName, 0).getPath();
ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
- ps.pkg.mSetEnabled = ps.enabled;
- ps.pkg.mSetStopped = ps.stopped;
}
+ ps.pkg.mSetEnabled = ps.getEnabled(userId);
+ ps.pkg.mSetStopped = ps.getStopped(userId);
return generatePackageInfo(ps.pkg, flags);
}
return null;
}
- public ApplicationInfo getApplicationInfo(String packageName, int flags) {
+ @Override
+ public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
// writer
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
@@ -1702,7 +1715,7 @@
return mAndroidApplication;
}
if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
- return generateApplicationInfoFromSettingsLPw(packageName, flags);
+ return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
}
}
return null;
@@ -1758,16 +1771,13 @@
});
}
- public ActivityInfo getActivityInfo(ComponentName component, int flags) {
- return getActivityInfo(component, flags, Binder.getOrigCallingUser());
- }
-
- ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
+ @Override
+ public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
synchronized (mPackages) {
PackageParser.Activity a = mActivities.mActivities.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
- if (a != null && mSettings.isEnabledLPr(a.info, flags)) {
+ if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
return PackageParser.generateActivityInfo(a, flags, userId);
}
if (mResolveComponentName.equals(component)) {
@@ -1777,48 +1787,39 @@
return null;
}
- public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
- return getReceiverInfo(component, flags, Binder.getOrigCallingUser());
- }
-
- ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
+ @Override
+ public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
synchronized (mPackages) {
PackageParser.Activity a = mReceivers.mActivities.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getReceiverInfo " + component + ": " + a);
- if (a != null && mSettings.isEnabledLPr(a.info, flags)) {
+ if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
return PackageParser.generateActivityInfo(a, flags, userId);
}
}
return null;
}
- public ServiceInfo getServiceInfo(ComponentName component, int flags) {
- return getServiceInfo(component, flags, Binder.getOrigCallingUser());
- }
-
- ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
+ @Override
+ public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
synchronized (mPackages) {
PackageParser.Service s = mServices.mServices.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getServiceInfo " + component + ": " + s);
- if (s != null && mSettings.isEnabledLPr(s.info, flags)) {
+ if (s != null && mSettings.isEnabledLPr(s.info, flags, userId)) {
return PackageParser.generateServiceInfo(s, flags, userId);
}
}
return null;
}
- public ProviderInfo getProviderInfo(ComponentName component, int flags) {
- return getProviderInfo(component, flags, UserId.getUserId(Binder.getCallingUid()));
- }
-
- ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
+ @Override
+ public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
synchronized (mPackages) {
PackageParser.Provider p = mProvidersByComponent.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getProviderInfo " + component + ": " + p);
- if (p != null && mSettings.isEnabledLPr(p.info, flags)) {
+ if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
return PackageParser.generateProviderInfo(p, flags, userId);
}
}
@@ -1863,6 +1864,14 @@
}
}
+ private void checkValidCaller(int uid, int userId) {
+ if (UserId.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0)
+ return;
+
+ throw new SecurityException("Caller uid=" + uid
+ + " is not privileged to communicate with user=" + userId);
+ }
+
public int checkPermission(String permName, String pkgName) {
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(pkgName);
@@ -1997,7 +2006,7 @@
if (!async) {
mSettings.writeLPr();
} else {
- scheduleWriteSettingsLocked();
+ scheduleWriteSettingsLocked();
}
}
return added;
@@ -2232,14 +2241,15 @@
}
}
+ @Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
- int flags) {
- List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
- return chooseBestActivity(intent, resolvedType, flags, query);
+ int flags, int userId) {
+ List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
+ return chooseBestActivity(intent, resolvedType, flags, query, userId);
}
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
- int flags, List<ResolveInfo> query) {
+ int flags, List<ResolveInfo> query, int userId) {
if (query != null) {
final int N = query.size();
if (N == 1) {
@@ -2263,7 +2273,7 @@
// If we have saved a preference for a preferred activity for
// this Intent, use that.
ResolveInfo ri = findPreferredActivity(intent, resolvedType,
- flags, query, r0.priority);
+ flags, query, r0.priority, userId);
if (ri != null) {
return ri;
}
@@ -2274,7 +2284,7 @@
}
ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
- int flags, List<ResolveInfo> query, int priority) {
+ int flags, List<ResolveInfo> query, int priority, int userId) {
// writer
synchronized (mPackages) {
if (intent.getSelector() != null) {
@@ -2283,7 +2293,7 @@
if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
List<PreferredActivity> prefs =
mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
- (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
if (prefs != null && prefs.size() > 0) {
// First figure out how good the original match set is.
// We will only allow preferred activities that came
@@ -2317,7 +2327,7 @@
if (pa.mPref.mMatch != match) {
continue;
}
- final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, flags);
+ final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, flags, userId);
if (DEBUG_PREFERRED) {
Log.v(TAG, "Got preferred activity:");
if (ai != null) {
@@ -2367,8 +2377,9 @@
return null;
}
+ @Override
public List<ResolveInfo> queryIntentActivities(Intent intent,
- String resolvedType, int flags) {
+ String resolvedType, int flags, int userId) {
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -2379,7 +2390,7 @@
if (comp != null) {
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
- final ActivityInfo ai = getActivityInfo(comp, flags);
+ final ActivityInfo ai = getActivityInfo(comp, flags, userId);
if (ai != null) {
final ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
@@ -2392,24 +2403,25 @@
synchronized (mPackages) {
final String pkgName = intent.getPackage();
if (pkgName == null) {
- return mActivities.queryIntent(intent, resolvedType, flags);
+ return mActivities.queryIntent(intent, resolvedType, flags, userId);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
return mActivities.queryIntentForPackage(intent, resolvedType, flags,
- pkg.activities);
+ pkg.activities, userId);
}
return new ArrayList<ResolveInfo>();
}
}
+ @Override
public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
Intent[] specifics, String[] specificTypes, Intent intent,
- String resolvedType, int flags) {
+ String resolvedType, int flags, int userId) {
final String resultsAction = intent.getAction();
List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
- | PackageManager.GET_RESOLVED_FILTER);
+ | PackageManager.GET_RESOLVED_FILTER, userId);
if (DEBUG_INTENT_MATCHING) {
Log.v(TAG, "Query " + intent + ": " + results);
@@ -2452,7 +2464,7 @@
ri = resolveIntent(
sintent,
specificTypes != null ? specificTypes[i] : null,
- flags);
+ flags, userId);
if (ri == null) {
continue;
}
@@ -2463,7 +2475,7 @@
comp = new ComponentName(ai.applicationInfo.packageName,
ai.name);
} else {
- ai = getActivityInfo(comp, flags);
+ ai = getActivityInfo(comp, flags, userId);
if (ai == null) {
continue;
}
@@ -2572,7 +2584,9 @@
return results;
}
- public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags) {
+ @Override
+ public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
+ int userId) {
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -2582,7 +2596,7 @@
}
if (comp != null) {
List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
- ActivityInfo ai = getReceiverInfo(comp, flags);
+ ActivityInfo ai = getReceiverInfo(comp, flags, userId);
if (ai != null) {
ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
@@ -2595,18 +2609,20 @@
synchronized (mPackages) {
String pkgName = intent.getPackage();
if (pkgName == null) {
- return mReceivers.queryIntent(intent, resolvedType, flags);
+ return mReceivers.queryIntent(intent, resolvedType, flags, userId);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
- return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers);
+ return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,
+ userId);
}
return null;
}
}
- public ResolveInfo resolveService(Intent intent, String resolvedType, int flags) {
- List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags);
+ @Override
+ public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
+ List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
if (query != null) {
if (query.size() >= 1) {
// If there is more than one service with the same priority,
@@ -2617,7 +2633,9 @@
return null;
}
- public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags) {
+ @Override
+ public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
+ int userId) {
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -2627,7 +2645,7 @@
}
if (comp != null) {
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
- final ServiceInfo si = getServiceInfo(comp, flags);
+ final ServiceInfo si = getServiceInfo(comp, flags, userId);
if (si != null) {
final ResolveInfo ri = new ResolveInfo();
ri.serviceInfo = si;
@@ -2640,11 +2658,12 @@
synchronized (mPackages) {
String pkgName = intent.getPackage();
if (pkgName == null) {
- return mServices.queryIntent(intent, resolvedType, flags);
+ return mServices.queryIntent(intent, resolvedType, flags, userId);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
- return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services);
+ return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
+ userId);
}
return null;
}
@@ -2669,6 +2688,7 @@
final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
final String[] keys;
+ int userId = UserId.getCallingUserId();
// writer
synchronized (mPackages) {
@@ -2689,7 +2709,7 @@
if (listUninstalled) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
- pi = generatePackageInfoFromSettingsLPw(ps.name, flags);
+ pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
}
} else {
final PackageParser.Package p = mPackages.get(packageName);
@@ -2711,8 +2731,9 @@
return list;
}
+ @Override
public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags,
- String lastRead) {
+ String lastRead, int userId) {
final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>();
final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
final String[] keys;
@@ -2728,7 +2749,6 @@
Arrays.sort(keys);
int i = getContinuationPoint(keys, lastRead);
final int N = keys.length;
- final int userId = UserId.getUserId(Binder.getCallingUid());
while (i < N) {
final String packageName = keys[i++];
@@ -2737,7 +2757,7 @@
if (listUninstalled) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
- ai = generateApplicationInfoFromSettingsLPw(ps.name, flags);
+ ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
}
} else {
final PackageParser.Package p = mPackages.get(packageName);
@@ -2779,16 +2799,16 @@
return finalList;
}
- public ProviderInfo resolveContentProvider(String name, int flags) {
+ @Override
+ public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
// reader
synchronized (mPackages) {
final PackageParser.Provider provider = mProviders.get(name);
return provider != null
- && mSettings.isEnabledLPr(provider.info, flags)
+ && mSettings.isEnabledLPr(provider.info, flags, userId)
&& (!mSafeMode || (provider.info.applicationInfo.flags
&ApplicationInfo.FLAG_SYSTEM) != 0)
- ? PackageParser.generateProviderInfo(provider, flags,
- UserId.getUserId(Binder.getCallingUid()))
+ ? PackageParser.generateProviderInfo(provider, flags, userId)
: null;
}
}
@@ -2824,15 +2844,15 @@
// reader
synchronized (mPackages) {
final Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
- final int userId = UserId.getUserId(Binder.getCallingUid());
+ final int userId = processName != null ?
+ UserId.getUserId(uid) : UserId.getCallingUserId();
while (i.hasNext()) {
final PackageParser.Provider p = i.next();
if (p.info.authority != null
&& (processName == null
|| (p.info.processName.equals(processName)
- && UserId.getAppId(p.info.applicationInfo.uid)
- == UserId.getAppId(uid)))
- && mSettings.isEnabledLPr(p.info, flags)
+ && UserId.isSameApp(p.info.applicationInfo.uid, uid)))
+ && mSettings.isEnabledLPr(p.info, flags, userId)
&& (!mSafeMode
|| (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
if (finalList == null) {
@@ -3482,7 +3502,7 @@
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
- pkg.applicationInfo.uid = pkgSetting.userId;
+ pkg.applicationInfo.uid = pkgSetting.uid;
pkg.mExtras = pkgSetting;
if (!verifySignaturesLP(pkgSetting, pkg)) {
@@ -4480,19 +4500,20 @@
private final class ActivityIntentResolver
extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
- boolean defaultOnly) {
+ boolean defaultOnly, int userId) {
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
- return super.queryIntent(intent, resolvedType, defaultOnly);
+ return super.queryIntent(intent, resolvedType, defaultOnly, userId);
}
- public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags) {
+ public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+ int userId) {
mFlags = flags;
return super.queryIntent(intent, resolvedType,
- (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
}
public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
- int flags, ArrayList<PackageParser.Activity> packageActivities) {
+ int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {
if (packageActivities == null) {
return null;
}
@@ -4509,7 +4530,7 @@
listCut.add(intentFilters);
}
}
- return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
+ return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
}
public final void addActivity(PackageParser.Activity a, String type) {
@@ -4574,7 +4595,7 @@
}
@Override
- protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter) {
+ protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
PackageParser.Package p = filter.activity.owner;
if (p != null) {
PackageSetting ps = (PackageSetting)p.mExtras;
@@ -4582,7 +4603,7 @@
// System apps are never considered stopped for purposes of
// filtering, because there may be no way for the user to
// actually re-launch them.
- return ps.stopped && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
+ return ps.getStopped(userId) && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
}
}
return false;
@@ -4595,8 +4616,8 @@
@Override
protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
- int match) {
- if (!mSettings.isEnabledLPr(info.activity.info, mFlags)) {
+ int match, int userId) {
+ if (!mSettings.isEnabledLPr(info.activity.info, mFlags, userId)) {
return null;
}
final PackageParser.Activity activity = info.activity;
@@ -4605,8 +4626,7 @@
return null;
}
final ResolveInfo res = new ResolveInfo();
- res.activityInfo = PackageParser.generateActivityInfo(activity, mFlags,
- Binder.getOrigCallingUser());
+ res.activityInfo = PackageParser.generateActivityInfo(activity, mFlags, userId);
if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
res.filter = info;
}
@@ -4660,19 +4680,20 @@
private final class ServiceIntentResolver
extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
- boolean defaultOnly) {
+ boolean defaultOnly, int userId) {
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
- return super.queryIntent(intent, resolvedType, defaultOnly);
+ return super.queryIntent(intent, resolvedType, defaultOnly, userId);
}
- public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags) {
+ public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+ int userId) {
mFlags = flags;
return super.queryIntent(intent, resolvedType,
- (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
}
public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
- int flags, ArrayList<PackageParser.Service> packageServices) {
+ int flags, ArrayList<PackageParser.Service> packageServices, int userId) {
if (packageServices == null) {
return null;
}
@@ -4689,7 +4710,7 @@
listCut.add(intentFilters);
}
}
- return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
+ return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
}
public final void addService(PackageParser.Service s) {
@@ -4749,7 +4770,7 @@
}
@Override
- protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter) {
+ protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
PackageParser.Package p = filter.service.owner;
if (p != null) {
PackageSetting ps = (PackageSetting)p.mExtras;
@@ -4757,7 +4778,8 @@
// System apps are never considered stopped for purposes of
// filtering, because there may be no way for the user to
// actually re-launch them.
- return ps.stopped && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
+ return ps.getStopped(userId)
+ && (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0;
}
}
return false;
@@ -4770,9 +4792,9 @@
@Override
protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
- int match) {
+ int match, int userId) {
final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
- if (!mSettings.isEnabledLPr(info.service.info, mFlags)) {
+ if (!mSettings.isEnabledLPr(info.service.info, mFlags, userId)) {
return null;
}
final PackageParser.Service service = info.service;
@@ -4781,8 +4803,7 @@
return null;
}
final ResolveInfo res = new ResolveInfo();
- res.serviceInfo = PackageParser.generateServiceInfo(service, mFlags,
- Binder.getOrigCallingUser());
+ res.serviceInfo = PackageParser.generateServiceInfo(service, mFlags, userId);
if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
res.filter = filter;
}
@@ -5635,14 +5656,14 @@
* do, then we'll defer to them to verify the packages.
*/
final int requiredUid = mRequiredVerifierPackage == null ? -1
- : getPackageUid(mRequiredVerifierPackage);
+ : getPackageUid(mRequiredVerifierPackage, 0);
if (requiredUid != -1 && isVerificationEnabled()) {
final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
verification.setDataAndType(packageURI, PACKAGE_MIME_TYPE);
verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
- PackageManager.GET_DISABLED_COMPONENTS);
+ PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
if (DEBUG_VERIFY) {
Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
@@ -7316,17 +7337,19 @@
return ret;
}
+ @Override
public void clearApplicationUserData(final String packageName,
- final IPackageDataObserver observer) {
+ final IPackageDataObserver observer, final int userId) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CLEAR_APP_USER_DATA, null);
+ checkValidCaller(Binder.getCallingUid(), userId);
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
final boolean succeeded;
synchronized (mInstallLock) {
- succeeded = clearApplicationUserDataLI(packageName);
+ succeeded = clearApplicationUserDataLI(packageName, userId);
}
if (succeeded) {
// invoke DeviceStorageMonitor's update method to clear any notifications
@@ -7347,7 +7370,7 @@
});
}
- private boolean clearApplicationUserDataLI(String packageName) {
+ private boolean clearApplicationUserDataLI(String packageName, int userId) {
if (packageName == null) {
Slog.w(TAG, "Attempt to delete null packageName.");
return false;
@@ -7379,7 +7402,7 @@
return false;
}
}
- int retCode = mInstaller.clearUserData(packageName, 0); // TODO - correct userId
+ int retCode = mInstaller.clearUserData(packageName, userId);
if (retCode < 0) {
Slog.w(TAG, "Couldn't remove cache files for package: "
+ packageName);
@@ -7393,12 +7416,13 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_CACHE_FILES, null);
// Queue up an async operation since the package deletion may take a little while.
+ final int userId = UserId.getCallingUserId();
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
final boolean succeded;
synchronized (mInstallLock) {
- succeded = deleteApplicationCacheFilesLI(packageName);
+ succeded = deleteApplicationCacheFilesLI(packageName, userId);
}
if(observer != null) {
try {
@@ -7411,7 +7435,7 @@
});
}
- private boolean deleteApplicationCacheFilesLI(String packageName) {
+ private boolean deleteApplicationCacheFilesLI(String packageName, int userId) {
if (packageName == null) {
Slog.w(TAG, "Attempt to delete null packageName.");
return false;
@@ -7429,6 +7453,7 @@
Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
return false;
}
+ // TODO: Pass userId to deleteCacheFiles
int retCode = mInstaller.deleteCacheFiles(packageName);
if (retCode < 0) {
Slog.w(TAG, "Couldn't remove cache files for package: "
@@ -7695,19 +7720,21 @@
return num;
}
+ @Override
public void setApplicationEnabledSetting(String appPackageName,
- int newState, int flags) {
- setEnabledSetting(appPackageName, null, newState, flags);
+ int newState, int flags, int userId) {
+ setEnabledSetting(appPackageName, null, newState, flags, userId);
}
+ @Override
public void setComponentEnabledSetting(ComponentName componentName,
- int newState, int flags) {
+ int newState, int flags, int userId) {
setEnabledSetting(componentName.getPackageName(),
- componentName.getClassName(), newState, flags);
+ componentName.getClassName(), newState, flags, userId);
}
private void setEnabledSetting(
- final String packageName, String className, int newState, final int flags) {
+ final String packageName, String className, int newState, final int flags, int userId) {
if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
|| newState == COMPONENT_ENABLED_STATE_ENABLED
|| newState == COMPONENT_ENABLED_STATE_DISABLED
@@ -7719,6 +7746,7 @@
final int uid = Binder.getCallingUid();
final int permission = mContext.checkCallingPermission(
android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
+ checkValidCaller(uid, userId);
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
boolean sendNow = false;
boolean isApp = (className == null);
@@ -7738,19 +7766,20 @@
"Unknown component: " + packageName
+ "/" + className);
}
- if (!allowedByPermission && (!UserId.isSameApp(uid, pkgSetting.userId))) {
+ // Allow root and verify that userId is not being specified by a different user
+ if (!allowedByPermission && !UserId.isSameApp(uid, pkgSetting.uid)) {
throw new SecurityException(
"Permission Denial: attempt to change component state from pid="
+ Binder.getCallingPid()
- + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
+ + ", uid=" + uid + ", package uid=" + pkgSetting.uid);
}
if (className == null) {
// We're dealing with an application/package level state change
- if (pkgSetting.enabled == newState) {
+ if (pkgSetting.getEnabled(userId) == newState) {
// Nothing to do
return;
}
- pkgSetting.enabled = newState;
+ pkgSetting.setEnabled(newState, userId);
pkgSetting.pkg.mSetEnabled = newState;
} else {
// We're dealing with a component level state change
@@ -7767,17 +7796,17 @@
}
switch (newState) {
case COMPONENT_ENABLED_STATE_ENABLED:
- if (!pkgSetting.enableComponentLPw(className)) {
+ if (!pkgSetting.enableComponentLPw(className, userId)) {
return;
}
break;
case COMPONENT_ENABLED_STATE_DISABLED:
- if (!pkgSetting.disableComponentLPw(className)) {
+ if (!pkgSetting.disableComponentLPw(className, userId)) {
return;
}
break;
case COMPONENT_ENABLED_STATE_DEFAULT:
- if (!pkgSetting.restoreComponentLPw(className)) {
+ if (!pkgSetting.restoreComponentLPw(className, userId)) {
return;
}
break;
@@ -7786,8 +7815,8 @@
return;
}
}
- mSettings.writeLPr();
- packageUid = pkgSetting.userId;
+ mSettings.writePackageRestrictionsLPr(userId);
+ packageUid = pkgSetting.uid;
components = mPendingBroadcasts.get(packageName);
final boolean newPackage = components == null;
if (newPackage) {
@@ -7838,16 +7867,17 @@
sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null);
}
- public void setPackageStoppedState(String packageName, boolean stopped) {
+ public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
final int uid = Binder.getCallingUid();
final int permission = mContext.checkCallingOrSelfPermission(
android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
+ checkValidCaller(uid, userId);
// writer
synchronized (mPackages) {
if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
- uid)) {
- scheduleWriteStoppedPackagesLocked();
+ uid, userId)) {
+ scheduleWritePackageRestrictionsLocked(userId);
}
}
}
@@ -7859,17 +7889,23 @@
}
}
- public int getApplicationEnabledSetting(String packageName) {
+ @Override
+ public int getApplicationEnabledSetting(String packageName, int userId) {
+ int uid = Binder.getCallingUid();
+ checkValidCaller(uid, userId);
// reader
synchronized (mPackages) {
- return mSettings.getApplicationEnabledSettingLPr(packageName);
+ return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
}
}
- public int getComponentEnabledSetting(ComponentName componentName) {
+ @Override
+ public int getComponentEnabledSetting(ComponentName componentName, int userId) {
+ int uid = Binder.getCallingUid();
+ checkValidCaller(uid, userId);
// reader
synchronized (mPackages) {
- return mSettings.getComponentEnabledSettingLPr(componentName);
+ return mSettings.getComponentEnabledSettingLPr(componentName, userId);
}
}
@@ -8073,7 +8109,7 @@
pw.print(" Required: ");
pw.print(mRequiredVerifierPackage);
pw.print(" (uid=");
- pw.print(getPackageUid(mRequiredVerifierPackage));
+ pw.print(getPackageUid(mRequiredVerifierPackage, 0));
pw.println(")");
}
@@ -8338,7 +8374,7 @@
+ " at code path: " + ps.codePathString);
// We do have a valid package installed on sdcard
processCids.put(args, ps.codePathString);
- int uid = ps.userId;
+ int uid = ps.uid;
if (uid != -1) {
uidList[num++] = uid;
}
diff --git a/services/java/com/android/server/pm/PackageSetting.java b/services/java/com/android/server/pm/PackageSetting.java
index efdc2b3..48ed9bf 100644
--- a/services/java/com/android/server/pm/PackageSetting.java
+++ b/services/java/com/android/server/pm/PackageSetting.java
@@ -24,7 +24,7 @@
* Settings data for a particular package we know about.
*/
final class PackageSetting extends PackageSettingBase {
- int userId;
+ int uid;
PackageParser.Package pkg;
SharedUserSetting sharedUser;
@@ -41,7 +41,7 @@
PackageSetting(PackageSetting orig) {
super(orig);
- userId = orig.userId;
+ uid = orig.uid;
pkg = orig.pkg;
sharedUser = orig.sharedUser;
}
@@ -50,6 +50,6 @@
public String toString() {
return "PackageSetting{"
+ Integer.toHexString(System.identityHashCode(this))
- + " " + name + "/" + userId + "}";
+ + " " + name + "/" + uid + "}";
}
}
\ No newline at end of file
diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/java/com/android/server/pm/PackageSettingBase.java
index e2f83ad..b7cf8d6 100644
--- a/services/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/java/com/android/server/pm/PackageSettingBase.java
@@ -20,6 +20,8 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
import java.io.File;
import java.util.HashSet;
@@ -62,20 +64,22 @@
// Whether this package is currently stopped, thus can not be
// started until explicitly launched by the user.
- public boolean stopped;
+ private SparseArray<Boolean> stopped = new SparseArray<Boolean>();
// Set to true if we have never launched this app.
- public boolean notLaunched;
+ private SparseArray<Boolean> notLaunched = new SparseArray<Boolean>();
/* Explicitly disabled components */
- HashSet<String> disabledComponents = new HashSet<String>(0);
+ private SparseArray<HashSet<String>> disabledComponents = new SparseArray<HashSet<String>>();
/* Explicitly enabled components */
- HashSet<String> enabledComponents = new HashSet<String>(0);
- int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+ private SparseArray<HashSet<String>> enabledComponents = new SparseArray<HashSet<String>>();
+ /* Enabled state */
+ private SparseIntArray enabled = new SparseIntArray();
+
int installStatus = PKG_INSTALL_COMPLETE;
PackageSettingBase origPackage;
-
+
/* package name of the app that installed this package */
String installerPackageName;
PackageSettingBase(String name, String realName, File codePath, File resourcePath,
@@ -111,14 +115,12 @@
permissionsFixed = base.permissionsFixed;
haveGids = base.haveGids;
- stopped = base.stopped;
notLaunched = base.notLaunched;
- disabledComponents = (HashSet<String>) base.disabledComponents.clone();
-
- enabledComponents = (HashSet<String>) base.enabledComponents.clone();
-
- enabled = base.enabled;
+ disabledComponents = (SparseArray<HashSet<String>>) base.disabledComponents.clone();
+ enabledComponents = (SparseArray<HashSet<String>>) base.enabledComponents.clone();
+ enabled = (SparseIntArray) base.enabled.clone();
+ stopped = (SparseArray<Boolean>) base.stopped.clone();
installStatus = base.installStatus;
origPackage = base.origPackage;
@@ -177,31 +179,98 @@
installStatus = base.installStatus;
}
- boolean enableComponentLPw(String componentClassName) {
- boolean changed = disabledComponents.remove(componentClassName);
- changed |= enabledComponents.add(componentClassName);
+ void setEnabled(int state, int userId) {
+ enabled.put(userId, state);
+ }
+
+ int getEnabled(int userId) {
+ return enabled.get(userId, COMPONENT_ENABLED_STATE_DEFAULT);
+ }
+
+ boolean getStopped(int userId) {
+ return stopped.get(userId, false);
+ }
+
+ void setStopped(boolean stop, int userId) {
+ stopped.put(userId, stop);
+ }
+
+ boolean getNotLaunched(int userId) {
+ return notLaunched.get(userId, false);
+ }
+
+ void setNotLaunched(boolean stop, int userId) {
+ notLaunched.put(userId, stop);
+ }
+
+ HashSet<String> getEnabledComponents(int userId) {
+ return getComponentHashSet(enabledComponents, userId);
+ }
+
+ HashSet<String> getDisabledComponents(int userId) {
+ return getComponentHashSet(disabledComponents, userId);
+ }
+
+ void setEnabledComponents(HashSet<String> components, int userId) {
+ enabledComponents.put(userId, components);
+ }
+
+ void setDisabledComponents(HashSet<String> components, int userId) {
+ disabledComponents.put(userId, components);
+ }
+
+ private HashSet<String> getComponentHashSet(SparseArray<HashSet<String>> setArray, int userId) {
+ HashSet<String> set = setArray.get(userId);
+ if (set == null) {
+ set = new HashSet<String>(1);
+ setArray.put(userId, set);
+ }
+ return set;
+ }
+
+ void addDisabledComponent(String componentClassName, int userId) {
+ HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+ disabled.add(componentClassName);
+ }
+
+ void addEnabledComponent(String componentClassName, int userId) {
+ HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+ enabled.add(componentClassName);
+ }
+
+ boolean enableComponentLPw(String componentClassName, int userId) {
+ HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+ HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+ boolean changed = disabled.remove(componentClassName);
+ changed |= enabled.add(componentClassName);
return changed;
}
- boolean disableComponentLPw(String componentClassName) {
- boolean changed = enabledComponents.remove(componentClassName);
- changed |= disabledComponents.add(componentClassName);
+ boolean disableComponentLPw(String componentClassName, int userId) {
+ HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+ HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+ boolean changed = enabled.remove(componentClassName);
+ changed |= disabled.add(componentClassName);
return changed;
}
- boolean restoreComponentLPw(String componentClassName) {
- boolean changed = enabledComponents.remove(componentClassName);
- changed |= disabledComponents.remove(componentClassName);
+ boolean restoreComponentLPw(String componentClassName, int userId) {
+ HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+ HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+ boolean changed = enabled.remove(componentClassName);
+ changed |= disabled.remove(componentClassName);
return changed;
}
- int getCurrentEnabledStateLPr(String componentName) {
- if (enabledComponents.contains(componentName)) {
+ int getCurrentEnabledStateLPr(String componentName, int userId) {
+ HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+ HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+ if (enabled.contains(componentName)) {
return COMPONENT_ENABLED_STATE_ENABLED;
- } else if (disabledComponents.contains(componentName)) {
+ } else if (disabled.contains(componentName)) {
return COMPONENT_ENABLED_STATE_DISABLED;
} else {
return COMPONENT_ENABLED_STATE_DEFAULT;
}
}
-}
\ No newline at end of file
+}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 363d020..b541c8c 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -32,6 +32,7 @@
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -40,11 +41,14 @@
import android.content.pm.PackageParser;
import android.content.pm.PermissionInfo;
import android.content.pm.Signature;
+import android.content.pm.UserInfo;
import android.content.pm.VerifierDeviceIdentity;
import android.os.Binder;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserId;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -63,6 +67,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import libcore.io.IoUtils;
@@ -78,6 +83,17 @@
private static final String TAG_READ_EXTERNAL_STORAGE = "read-external-storage";
private static final String ATTR_ENFORCEMENT = "enforcement";
+ private static final String TAG_ITEM = "item";
+ private static final String TAG_DISABLED_COMPONENTS = "disabled-components";
+ private static final String TAG_ENABLED_COMPONENTS = "enabled-components";
+ private static final String TAG_PACKAGE_RESTRICTIONS = "package-restrictions";
+ private static final String TAG_PACKAGE = "pkg";
+
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_NOT_LAUNCHED = "nl";
+ private static final String ATTR_ENABLED = "enabled";
+ private static final String ATTR_STOPPED = "stopped";
+
private final File mSettingsFilename;
private final File mBackupSettingsFilename;
private final File mPackageListFilename;
@@ -153,19 +169,24 @@
*/
private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>();
+ private final File mSystemDir;
Settings() {
- File dataDir = Environment.getDataDirectory();
- File systemDir = new File(dataDir, "system");
- systemDir.mkdirs();
- FileUtils.setPermissions(systemDir.toString(),
+ this(Environment.getDataDirectory());
+ }
+
+ Settings(File dataDir) {
+ mSystemDir = new File(dataDir, "system");
+ mSystemDir.mkdirs();
+ FileUtils.setPermissions(mSystemDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);
- mSettingsFilename = new File(systemDir, "packages.xml");
- mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
- mPackageListFilename = new File(systemDir, "packages.list");
- mStoppedPackagesFilename = new File(systemDir, "packages-stopped.xml");
- mBackupStoppedPackagesFilename = new File(systemDir, "packages-stopped-backup.xml");
+ mSettingsFilename = new File(mSystemDir, "packages.xml");
+ mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
+ mPackageListFilename = new File(mSystemDir, "packages.list");
+ // Deprecated: Needed for migration
+ mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
+ mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}
PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
@@ -254,7 +275,7 @@
p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
- p.nativeLibraryPathString, p.userId, p.versionCode, p.pkgFlags);
+ p.nativeLibraryPathString, p.uid, p.versionCode, p.pkgFlags);
mDisabledSysPackages.remove(name);
return ret;
}
@@ -263,7 +284,7 @@
String nativeLibraryPathString, int uid, int vc, int pkgFlags) {
PackageSetting p = mPackages.get(name);
if (p != null) {
- if (p.userId == uid) {
+ if (p.uid == uid) {
return p;
}
PackageManagerService.reportSettingsProblem(Log.ERROR,
@@ -272,7 +293,7 @@
}
p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString,
vc, pkgFlags);
- p.userId = uid;
+ p.uid = uid;
if (addUserIdLPw(uid, p, name)) {
mPackages.put(name, p);
return p;
@@ -323,7 +344,7 @@
}
}
}
-
+
private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
String nativeLibraryPathString, int vc, int pkgFlags, boolean create, boolean add) {
@@ -335,13 +356,13 @@
// This is an updated system app with versions in both system
// and data partition. Just let the most recent version
// take precedence.
- Slog.w(PackageManagerService.TAG, "Trying to update system app code path from " +
- p.codePathString + " to " + codePath.toString());
+ Slog.w(PackageManagerService.TAG, "Trying to update system app code path from "
+ + p.codePathString + " to " + codePath.toString());
} else {
// Just a change in the code path is not an issue, but
// let's log a message about it.
- Slog.i(PackageManagerService.TAG, "Package " + name + " codePath changed from " + p.codePath
- + " to " + codePath + "; Retaining data and using new");
+ Slog.i(PackageManagerService.TAG, "Package " + name + " codePath changed from "
+ + p.codePath + " to " + codePath + "; Retaining data and using new");
/*
* Since we've changed paths, we need to prefer the new
* native library path over the one stored in the
@@ -378,15 +399,15 @@
// We are consuming the data from an existing package.
p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
nativeLibraryPathString, vc, pkgFlags);
- if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package " + name
- + " is adopting original package " + origPackage.name);
+ if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
+ + name + " is adopting original package " + origPackage.name);
// Note that we will retain the new package's signature so
// that we can keep its data.
PackageSignatures s = p.signatures;
p.copyFrom(origPackage);
p.signatures = s;
p.sharedUser = origPackage.sharedUser;
- p.userId = origPackage.userId;
+ p.uid = origPackage.uid;
p.origPackage = origPackage;
mRenamedPackages.put(name, origPackage.name);
name = origPackage.name;
@@ -404,11 +425,17 @@
e.fillInStackTrace();
Slog.i(PackageManagerService.TAG, "Stopping package " + name, e);
}
- p.stopped = true;
- p.notLaunched = true;
+ List<UserInfo> users = getAllUsers();
+ if (users != null) {
+ for (UserInfo user : users) {
+ p.setStopped(true, user.id);
+ p.setNotLaunched(true, user.id);
+ writePackageRestrictionsLPr(user.id);
+ }
+ }
}
if (sharedUser != null) {
- p.userId = sharedUser.userId;
+ p.uid = sharedUser.userId;
} else {
// Clone the setting here for disabled system packages
PackageSetting dis = mDisabledSysPackages.get(name);
@@ -420,21 +447,31 @@
if (dis.signatures.mSignatures != null) {
p.signatures.mSignatures = dis.signatures.mSignatures.clone();
}
- p.userId = dis.userId;
+ p.uid = dis.uid;
// Clone permissions
p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
// Clone component info
- p.disabledComponents = new HashSet<String>(dis.disabledComponents);
- p.enabledComponents = new HashSet<String>(dis.enabledComponents);
+ List<UserInfo> users = getAllUsers();
+ if (users != null) {
+ for (UserInfo user : users) {
+ int userId = user.id;
+ p.setDisabledComponents(
+ new HashSet<String>(dis.getDisabledComponents(userId)),
+ userId);
+ p.setEnabledComponents(
+ new HashSet<String>(dis.getEnabledComponents(userId)),
+ userId);
+ }
+ }
// Add new setting to list of user ids
- addUserIdLPw(p.userId, p, name);
+ addUserIdLPw(p.uid, p, name);
} else {
// Assign new user id
- p.userId = newUserIdLPw(p);
+ p.uid = newUserIdLPw(p);
}
}
}
- if (p.userId < 0) {
+ if (p.uid < 0) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Package " + name + " could not be assigned a valid uid");
return null;
@@ -450,8 +487,8 @@
void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
p.pkg = pkg;
- pkg.mSetEnabled = p.enabled;
- pkg.mSetStopped = p.stopped;
+ // pkg.mSetEnabled = p.getEnabled(userId);
+ // pkg.mSetStopped = p.getStopped(userId);
final String codePath = pkg.applicationInfo.sourceDir;
final String resourcePath = pkg.applicationInfo.publicSourceDir;
// Update code path if needed
@@ -475,18 +512,18 @@
p.nativeLibraryPathString = nativeLibraryPath;
}
// Update version code if needed
- if (pkg.mVersionCode != p.versionCode) {
+ if (pkg.mVersionCode != p.versionCode) {
p.versionCode = pkg.mVersionCode;
}
- // Update signatures if needed.
- if (p.signatures.mSignatures == null) {
- p.signatures.assignSignatures(pkg.mSignatures);
- }
- // If this app defines a shared user id initialize
- // the shared user signatures as well.
- if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
- p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
- }
+ // Update signatures if needed.
+ if (p.signatures.mSignatures == null) {
+ p.signatures.assignSignatures(pkg.mSignatures);
+ }
+ // If this app defines a shared user id initialize
+ // the shared user signatures as well.
+ if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
+ p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
+ }
addPackageSettingLPw(p, pkg.packageName, p.sharedUser);
}
@@ -502,9 +539,9 @@
+ p.sharedUser + " but is now " + sharedUser
+ "; I am not changing its files so it will probably fail!");
p.sharedUser.packages.remove(p);
- } else if (p.userId != sharedUser.userId) {
+ } else if (p.uid != sharedUser.userId) {
PackageManagerService.reportSettingsProblem(Log.ERROR,
- "Package " + p.name + " was user id " + p.userId
+ "Package " + p.name + " was user id " + p.uid
+ " but is now user " + sharedUser
+ " with id " + sharedUser.userId
+ "; I am not changing its files so it will probably fail!");
@@ -512,7 +549,7 @@
sharedUser.packages.add(p);
p.sharedUser = sharedUser;
- p.userId = sharedUser.userId;
+ p.uid = sharedUser.userId;
}
}
@@ -577,8 +614,8 @@
return p.sharedUser.userId;
}
} else {
- removeUserIdLPw(p.userId);
- return p.userId;
+ removeUserIdLPw(p.uid);
+ return p.uid;
}
}
return -1;
@@ -591,7 +628,7 @@
p.sharedUser.packages.remove(p);
p.sharedUser.packages.add(newp);
} else {
- replaceUserIdLPw(p.userId, newp);
+ replaceUserIdLPw(p.uid, newp);
}
}
mPackages.put(name, newp);
@@ -658,50 +695,269 @@
}
}
- void writeStoppedLPr() {
+ private File getUserPackagesStateFile(int userId) {
+ return new File(mSystemDir,
+ "users/" + userId + "/package-restrictions.xml");
+ }
+
+ private File getUserPackagesStateBackupFile(int userId) {
+ return new File(mSystemDir,
+ "users/" + userId + "/package-restrictions-backup.xml");
+ }
+
+ void writeAllUsersPackageRestrictionsLPr() {
+ List<UserInfo> users = getAllUsers();
+ if (users == null) return;
+
+ for (UserInfo user : users) {
+ writePackageRestrictionsLPr(user.id);
+ }
+ }
+
+ void readAllUsersPackageRestrictionsLPr() {
+ List<UserInfo> users = getAllUsers();
+ if (users == null) {
+ readPackageRestrictionsLPr(0);
+ return;
+ }
+
+ for (UserInfo user : users) {
+ readPackageRestrictionsLPr(user.id);
+ }
+ }
+
+ void readPackageRestrictionsLPr(int userId) {
+ FileInputStream str = null;
+ File userPackagesStateFile = getUserPackagesStateFile(userId);
+ File backupFile = getUserPackagesStateBackupFile(userId);
+ if (backupFile.exists()) {
+ try {
+ str = new FileInputStream(backupFile);
+ mReadMessages.append("Reading from backup stopped packages file\n");
+ PackageManagerService.reportSettingsProblem(Log.INFO,
+ "Need to read from backup stopped packages file");
+ if (userPackagesStateFile.exists()) {
+ // If both the backup and normal file exist, we
+ // ignore the normal one since it might have been
+ // corrupted.
+ Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file "
+ + userPackagesStateFile);
+ userPackagesStateFile.delete();
+ }
+ } catch (java.io.IOException e) {
+ // We'll try for the normal settings file.
+ }
+ }
+
+ try {
+ if (str == null) {
+ if (!userPackagesStateFile.exists()) {
+ mReadMessages.append("No stopped packages file found\n");
+ PackageManagerService.reportSettingsProblem(Log.INFO,
+ "No stopped packages file; "
+ + "assuming all started");
+ // At first boot, make sure no packages are stopped.
+ // We usually want to have third party apps initialize
+ // in the stopped state, but not at first boot.
+ for (PackageSetting pkg : mPackages.values()) {
+ pkg.setStopped(false, userId);
+ pkg.setNotLaunched(false, userId);
+ }
+ return;
+ }
+ str = new FileInputStream(userPackagesStateFile);
+ }
+ final XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(str, null);
+
+ int type;
+ while ((type=parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ ;
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ mReadMessages.append("No start tag found in package restrictions file\n");
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "No start tag found in package manager stopped packages");
+ return;
+ }
+
+ int outerDepth = parser.getDepth();
+ PackageSetting ps = null;
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if (tagName.equals(TAG_PACKAGE)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ ps = mPackages.get(name);
+ if (ps == null) {
+ Slog.w(PackageManagerService.TAG, "No package known for stopped package: "
+ + name);
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
+ int enabled = enabledStr == null ? COMPONENT_ENABLED_STATE_DEFAULT
+ : Integer.parseInt(enabledStr);
+ ps.setEnabled(enabled, userId);
+ String stoppedStr = parser.getAttributeValue(null, ATTR_STOPPED);
+ boolean stopped = stoppedStr == null ? false : Boolean.parseBoolean(stoppedStr);
+ ps.setStopped(stopped, userId);
+ String notLaunchedStr = parser.getAttributeValue(null, ATTR_NOT_LAUNCHED);
+ boolean notLaunched = stoppedStr == null ? false
+ : Boolean.parseBoolean(notLaunchedStr);
+ ps.setNotLaunched(notLaunched, userId);
+
+ int packageDepth = parser.getDepth();
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > packageDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ tagName = parser.getName();
+ if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
+ HashSet<String> components = readComponentsLPr(parser);
+ ps.setEnabledComponents(components, userId);
+ } else if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
+ HashSet<String> components = readComponentsLPr(parser);
+ ps.setDisabledComponents(components, userId);
+ }
+ }
+ } else {
+ Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+
+ str.close();
+
+ } catch (XmlPullParserException e) {
+ mReadMessages.append("Error reading: " + e.toString());
+ PackageManagerService.reportSettingsProblem(Log.ERROR,
+ "Error reading stopped packages: " + e);
+ Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
+
+ } catch (java.io.IOException e) {
+ mReadMessages.append("Error reading: " + e.toString());
+ PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
+ Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
+ }
+ }
+
+ private HashSet<String> readComponentsLPr(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ HashSet<String> components = new HashSet<String>();
+ int type;
+ int outerDepth = parser.getDepth();
+ String tagName;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ tagName = parser.getName();
+ if (tagName.equals(TAG_ITEM)) {
+ String componentName = parser.getAttributeValue(null, ATTR_NAME);
+ if (componentName != null) {
+ components.add(componentName);
+ }
+ }
+ }
+ return components;
+ }
+
+ void writePackageRestrictionsLPr(int userId) {
// Keep the old stopped packages around until we know the new ones have
// been successfully written.
- if (mStoppedPackagesFilename.exists()) {
+ File userPackagesStateFile = getUserPackagesStateFile(userId);
+ File backupFile = getUserPackagesStateBackupFile(userId);
+ new File(userPackagesStateFile.getParent()).mkdirs();
+ if (userPackagesStateFile.exists()) {
// Presence of backup settings file indicates that we failed
// to persist packages earlier. So preserve the older
// backup for future reference since the current packages
// might have been corrupted.
- if (!mBackupStoppedPackagesFilename.exists()) {
- if (!mStoppedPackagesFilename.renameTo(mBackupStoppedPackagesFilename)) {
- Log.wtf(PackageManagerService.TAG, "Unable to backup package manager stopped packages, "
+ if (!backupFile.exists()) {
+ if (!userPackagesStateFile.renameTo(backupFile)) {
+ Log.wtf(PackageManagerService.TAG, "Unable to backup user packages state file, "
+ "current changes will be lost at reboot");
return;
}
} else {
- mStoppedPackagesFilename.delete();
+ userPackagesStateFile.delete();
Slog.w(PackageManagerService.TAG, "Preserving older stopped packages backup");
}
}
try {
- final FileOutputStream fstr = new FileOutputStream(mStoppedPackagesFilename);
+ final FileOutputStream fstr = new FileOutputStream(userPackagesStateFile);
final BufferedOutputStream str = new BufferedOutputStream(fstr);
- //XmlSerializer serializer = XmlUtils.serializerInstance();
final XmlSerializer serializer = new FastXmlSerializer();
serializer.setOutput(str, "utf-8");
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
- serializer.startTag(null, "stopped-packages");
+ serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
for (final PackageSetting pkg : mPackages.values()) {
- if (pkg.stopped) {
- serializer.startTag(null, "pkg");
- serializer.attribute(null, "name", pkg.name);
- if (pkg.notLaunched) {
- serializer.attribute(null, "nl", "1");
+ if (pkg.getStopped(userId)
+ || pkg.getNotLaunched(userId)
+ || pkg.getEnabled(userId) != COMPONENT_ENABLED_STATE_DEFAULT
+ || pkg.getEnabledComponents(userId).size() > 0
+ || pkg.getDisabledComponents(userId).size() > 0) {
+ serializer.startTag(null, TAG_PACKAGE);
+ serializer.attribute(null, ATTR_NAME, pkg.name);
+ boolean stopped = pkg.getStopped(userId);
+ boolean notLaunched = pkg.getNotLaunched(userId);
+ int enabled = pkg.getEnabled(userId);
+ HashSet<String> enabledComponents = pkg.getEnabledComponents(userId);
+ HashSet<String> disabledComponents = pkg.getDisabledComponents(userId);
+
+ if (stopped) {
+ serializer.attribute(null, ATTR_STOPPED, "true");
}
- serializer.endTag(null, "pkg");
+ if (notLaunched) {
+ serializer.attribute(null, ATTR_NOT_LAUNCHED, "true");
+ }
+ if (enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
+ serializer.attribute(null, ATTR_ENABLED, Integer.toString(enabled));
+ }
+ if (enabledComponents.size() > 0) {
+ serializer.startTag(null, TAG_ENABLED_COMPONENTS);
+ for (final String name : enabledComponents) {
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
+ }
+ serializer.endTag(null, TAG_ENABLED_COMPONENTS);
+ }
+ if (disabledComponents.size() > 0) {
+ serializer.startTag(null, TAG_DISABLED_COMPONENTS);
+ for (final String name : disabledComponents) {
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
+ }
+ serializer.endTag(null, TAG_DISABLED_COMPONENTS);
+ }
+ serializer.endTag(null, TAG_PACKAGE);
}
}
- serializer.endTag(null, "stopped-packages");
+ serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
serializer.endDocument();
@@ -711,8 +967,8 @@
// New settings successfully written, old ones are no longer
// needed.
- mBackupStoppedPackagesFilename.delete();
- FileUtils.setPermissions(mStoppedPackagesFilename.toString(),
+ backupFile.delete();
+ FileUtils.setPermissions(userPackagesStateFile.toString(),
FileUtils.S_IRUSR|FileUtils.S_IWUSR
|FileUtils.S_IRGRP|FileUtils.S_IWGRP,
-1, -1);
@@ -720,26 +976,30 @@
// Done, all is good!
return;
} catch(java.io.IOException e) {
- Log.wtf(PackageManagerService.TAG, "Unable to write package manager stopped packages, "
+ Log.wtf(PackageManagerService.TAG,
+ "Unable to write package manager user packages state, "
+ " current changes will be lost at reboot", e);
}
// Clean up partially written files
- if (mStoppedPackagesFilename.exists()) {
- if (!mStoppedPackagesFilename.delete()) {
- Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: " + mStoppedPackagesFilename);
+ if (userPackagesStateFile.exists()) {
+ if (!userPackagesStateFile.delete()) {
+ Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: "
+ + mStoppedPackagesFilename);
}
}
}
// Note: assumed "stopped" field is already cleared in all packages.
+ // Legacy reader, used to read in the old file format after an upgrade. Not used after that.
void readStoppedLPw() {
FileInputStream str = null;
if (mBackupStoppedPackagesFilename.exists()) {
try {
str = new FileInputStream(mBackupStoppedPackagesFilename);
mReadMessages.append("Reading from backup stopped packages file\n");
- PackageManagerService.reportSettingsProblem(Log.INFO, "Need to read from backup stopped packages file");
+ PackageManagerService.reportSettingsProblem(Log.INFO,
+ "Need to read from backup stopped packages file");
if (mSettingsFilename.exists()) {
// If both the backup and normal file exist, we
// ignore the normal one since it might have been
@@ -757,14 +1017,14 @@
if (str == null) {
if (!mStoppedPackagesFilename.exists()) {
mReadMessages.append("No stopped packages file found\n");
- PackageManagerService.reportSettingsProblem(Log.INFO, "No stopped packages file file; "
- + "assuming all started");
+ PackageManagerService.reportSettingsProblem(Log.INFO,
+ "No stopped packages file file; assuming all started");
// At first boot, make sure no packages are stopped.
// We usually want to have third party apps initialize
// in the stopped state, but not at first boot.
for (PackageSetting pkg : mPackages.values()) {
- pkg.stopped = false;
- pkg.notLaunched = false;
+ pkg.setStopped(false, 0);
+ pkg.setNotLaunched(false, 0);
}
return;
}
@@ -796,16 +1056,17 @@
}
String tagName = parser.getName();
- if (tagName.equals("pkg")) {
- String name = parser.getAttributeValue(null, "name");
+ if (tagName.equals(TAG_PACKAGE)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
PackageSetting ps = mPackages.get(name);
if (ps != null) {
- ps.stopped = true;
- if ("1".equals(parser.getAttributeValue(null, "nl"))) {
- ps.notLaunched = true;
+ ps.setStopped(true, 0);
+ if ("1".equals(parser.getAttributeValue(null, ATTR_NOT_LAUNCHED))) {
+ ps.setNotLaunched(true, 0);
}
} else {
- Slog.w(PackageManagerService.TAG, "No package known for stopped package: " + name);
+ Slog.w(PackageManagerService.TAG,
+ "No package known for stopped package: " + name);
}
XmlUtils.skipCurrentTag(parser);
} else {
@@ -817,12 +1078,13 @@
str.close();
- } catch(XmlPullParserException e) {
+ } catch (XmlPullParserException e) {
mReadMessages.append("Error reading: " + e.toString());
- PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading stopped packages: " + e);
+ PackageManagerService.reportSettingsProblem(Log.ERROR,
+ "Error reading stopped packages: " + e);
Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
- } catch(java.io.IOException e) {
+ } catch (java.io.IOException e) {
mReadMessages.append("Error reading: " + e.toString());
PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
@@ -906,23 +1168,23 @@
serializer.startTag(null, "preferred-activities");
for (final PreferredActivity pa : mPreferredActivities.filterSet()) {
- serializer.startTag(null, "item");
+ serializer.startTag(null, TAG_ITEM);
pa.writeToXml(serializer);
- serializer.endTag(null, "item");
+ serializer.endTag(null, TAG_ITEM);
}
serializer.endTag(null, "preferred-activities");
for (final SharedUserSetting usr : mSharedUsers.values()) {
serializer.startTag(null, "shared-user");
- serializer.attribute(null, "name", usr.name);
+ serializer.attribute(null, ATTR_NAME, usr.name);
serializer.attribute(null, "userId",
Integer.toString(usr.userId));
usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
serializer.startTag(null, "perms");
for (String name : usr.grantedPermissions) {
- serializer.startTag(null, "item");
- serializer.attribute(null, "name", name);
- serializer.endTag(null, "item");
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
}
serializer.endTag(null, "perms");
serializer.endTag(null, "shared-user");
@@ -931,7 +1193,7 @@
if (mPackagesToBeCleaned.size() > 0) {
for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
serializer.startTag(null, "cleaning-package");
- serializer.attribute(null, "name", mPackagesToBeCleaned.get(i));
+ serializer.attribute(null, ATTR_NAME, mPackagesToBeCleaned.get(i));
serializer.endTag(null, "cleaning-package");
}
}
@@ -1016,8 +1278,7 @@
|FileUtils.S_IRGRP|FileUtils.S_IWGRP,
-1, -1);
- writeStoppedLPr();
-
+ writeAllUsersPackageRestrictionsLPr();
return;
} catch(XmlPullParserException e) {
@@ -1030,7 +1291,8 @@
// Clean up partially written files
if (mSettingsFilename.exists()) {
if (!mSettingsFilename.delete()) {
- Log.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: " + mSettingsFilename);
+ Log.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: "
+ + mSettingsFilename);
}
}
//Debug.stopMethodTracing();
@@ -1039,7 +1301,7 @@
void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg)
throws java.io.IOException {
serializer.startTag(null, "updated-package");
- serializer.attribute(null, "name", pkg.name);
+ serializer.attribute(null, ATTR_NAME, pkg.name);
if (pkg.realName != null) {
serializer.attribute(null, "realName", pkg.realName);
}
@@ -1055,9 +1317,9 @@
serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
}
if (pkg.sharedUser == null) {
- serializer.attribute(null, "userId", Integer.toString(pkg.userId));
+ serializer.attribute(null, "userId", Integer.toString(pkg.uid));
} else {
- serializer.attribute(null, "sharedUserId", Integer.toString(pkg.userId));
+ serializer.attribute(null, "sharedUserId", Integer.toString(pkg.uid));
}
serializer.startTag(null, "perms");
if (pkg.sharedUser == null) {
@@ -1072,9 +1334,9 @@
// this wont
// match the semantics of grantedPermissions. So write all
// permissions.
- serializer.startTag(null, "item");
- serializer.attribute(null, "name", name);
- serializer.endTag(null, "item");
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
}
}
}
@@ -1085,7 +1347,7 @@
void writePackageLPr(XmlSerializer serializer, final PackageSetting pkg)
throws java.io.IOException {
serializer.startTag(null, "package");
- serializer.attribute(null, "name", pkg.name);
+ serializer.attribute(null, ATTR_NAME, pkg.name);
if (pkg.realName != null) {
serializer.attribute(null, "realName", pkg.realName);
}
@@ -1102,16 +1364,13 @@
serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
if (pkg.sharedUser == null) {
- serializer.attribute(null, "userId", Integer.toString(pkg.userId));
+ serializer.attribute(null, "userId", Integer.toString(pkg.uid));
} else {
- serializer.attribute(null, "sharedUserId", Integer.toString(pkg.userId));
+ serializer.attribute(null, "sharedUserId", Integer.toString(pkg.uid));
}
if (pkg.uidError) {
serializer.attribute(null, "uidError", "true");
}
- if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
- serializer.attribute(null, "enabled", Integer.toString(pkg.enabled));
- }
if (pkg.installStatus == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {
serializer.attribute(null, "installStatus", "false");
}
@@ -1127,31 +1386,13 @@
// empty permissions list so permissionsFixed will
// be set.
for (final String name : pkg.grantedPermissions) {
- serializer.startTag(null, "item");
- serializer.attribute(null, "name", name);
- serializer.endTag(null, "item");
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
}
}
serializer.endTag(null, "perms");
}
- if (pkg.disabledComponents.size() > 0) {
- serializer.startTag(null, "disabled-components");
- for (final String name : pkg.disabledComponents) {
- serializer.startTag(null, "item");
- serializer.attribute(null, "name", name);
- serializer.endTag(null, "item");
- }
- serializer.endTag(null, "disabled-components");
- }
- if (pkg.enabledComponents.size() > 0) {
- serializer.startTag(null, "enabled-components");
- for (final String name : pkg.enabledComponents) {
- serializer.startTag(null, "item");
- serializer.attribute(null, "name", name);
- serializer.endTag(null, "item");
- }
- serializer.endTag(null, "enabled-components");
- }
serializer.endTag(null, "package");
}
@@ -1159,8 +1400,8 @@
void writePermissionLPr(XmlSerializer serializer, BasePermission bp)
throws XmlPullParserException, java.io.IOException {
if (bp.type != BasePermission.TYPE_BUILTIN && bp.sourcePackage != null) {
- serializer.startTag(null, "item");
- serializer.attribute(null, "name", bp.name);
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, bp.name);
serializer.attribute(null, "package", bp.sourcePackage);
if (bp.protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
serializer.attribute(null, "protection", Integer.toString(bp.protectionLevel));
@@ -1180,7 +1421,7 @@
}
}
}
- serializer.endTag(null, "item");
+ serializer.endTag(null, TAG_ITEM);
}
}
@@ -1198,7 +1439,7 @@
return ret;
}
- boolean readLPw() {
+ boolean readLPw(List<UserInfo> users) {
FileInputStream str = null;
if (mBackupSettingsFilename.exists()) {
try {
@@ -1273,7 +1514,7 @@
} else if (tagName.equals("updated-package")) {
readDisabledSysPackageLPw(parser);
} else if (tagName.equals("cleaning-package")) {
- String name = parser.getAttributeValue(null, "name");
+ String name = parser.getAttributeValue(null, ATTR_NAME);
if (name != null) {
mPackagesToBeCleaned.add(name);
}
@@ -1366,14 +1607,29 @@
final Iterator<PackageSetting> disabledIt = mDisabledSysPackages.values().iterator();
while (disabledIt.hasNext()) {
final PackageSetting disabledPs = disabledIt.next();
- final Object id = getUserIdLPr(disabledPs.userId);
+ final Object id = getUserIdLPr(disabledPs.uid);
if (id != null && id instanceof SharedUserSetting) {
disabledPs.sharedUser = (SharedUserSetting) id;
}
}
- readStoppedLPw();
-
+ if (mBackupStoppedPackagesFilename.exists()
+ || mStoppedPackagesFilename.exists()) {
+ // Read old file
+ readStoppedLPw();
+ mBackupStoppedPackagesFilename.delete();
+ mStoppedPackagesFilename.delete();
+ // Migrate to new file format
+ writePackageRestrictionsLPr(0);
+ } else {
+ if (users == null) {
+ readPackageRestrictionsLPr(0);
+ } else {
+ for (UserInfo user : users) {
+ readPackageRestrictionsLPr(user.id);
+ }
+ }
+ }
mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
+ mSharedUsers.size() + " shared uids\n");
@@ -1407,8 +1663,8 @@
}
final String tagName = parser.getName();
- if (tagName.equals("item")) {
- final String name = parser.getAttributeValue(null, "name");
+ if (tagName.equals(TAG_ITEM)) {
+ final String name = parser.getAttributeValue(null, ATTR_NAME);
final String sourcePackage = parser.getAttributeValue(null, "package");
final String ptype = parser.getAttributeValue(null, "type");
if (name != null && sourcePackage != null) {
@@ -1444,7 +1700,7 @@
private void readDisabledSysPackageLPw(XmlPullParser parser) throws XmlPullParserException,
IOException {
- String name = parser.getAttributeValue(null, "name");
+ String name = parser.getAttributeValue(null, ATTR_NAME);
String realName = parser.getAttributeValue(null, "realName");
String codePathStr = parser.getAttributeValue(null, "codePath");
String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
@@ -1497,10 +1753,10 @@
}
}
String idStr = parser.getAttributeValue(null, "userId");
- ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
- if (ps.userId <= 0) {
+ ps.uid = idStr != null ? Integer.parseInt(idStr) : 0;
+ if (ps.uid <= 0) {
String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
- ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
+ ps.uid = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
}
int outerDepth = parser.getDepth();
int type;
@@ -1541,7 +1797,7 @@
String version = null;
int versionCode = 0;
try {
- name = parser.getAttributeValue(null, "name");
+ name = parser.getAttributeValue(null, ATTR_NAME);
realName = parser.getAttributeValue(null, "realName");
idStr = parser.getAttributeValue(null, "userId");
uidError = parser.getAttributeValue(null, "uidError");
@@ -1672,17 +1928,18 @@
packageSetting.uidError = "true".equals(uidError);
packageSetting.installerPackageName = installerPackageName;
packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
- final String enabledStr = parser.getAttributeValue(null, "enabled");
+ // Handle legacy string here for single-user mode
+ final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
if (enabledStr != null) {
try {
- packageSetting.enabled = Integer.parseInt(enabledStr);
+ packageSetting.setEnabled(Integer.parseInt(enabledStr), 0 /* userId */);
} catch (NumberFormatException e) {
if (enabledStr.equalsIgnoreCase("true")) {
- packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
+ packageSetting.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 0);
} else if (enabledStr.equalsIgnoreCase("false")) {
- packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
+ packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0);
} else if (enabledStr.equalsIgnoreCase("default")) {
- packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+ packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0);
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: package " + name
@@ -1691,8 +1948,9 @@
}
}
} else {
- packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+ packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0);
}
+
final String installStatusStr = parser.getAttributeValue(null, "installStatus");
if (installStatusStr != null) {
if (installStatusStr.equalsIgnoreCase("false")) {
@@ -1711,10 +1969,11 @@
}
String tagName = parser.getName();
- if (tagName.equals("disabled-components")) {
- readDisabledComponentsLPw(packageSetting, parser);
- } else if (tagName.equals("enabled-components")) {
- readEnabledComponentsLPw(packageSetting, parser);
+ // Legacy
+ if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
+ readDisabledComponentsLPw(packageSetting, parser, 0);
+ } else if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
+ readEnabledComponentsLPw(packageSetting, parser, 0);
} else if (tagName.equals("sigs")) {
packageSetting.signatures.readXml(parser, mPastSignatures);
} else if (tagName.equals("perms")) {
@@ -1731,8 +1990,8 @@
}
}
- private void readDisabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser)
- throws IOException, XmlPullParserException {
+ private void readDisabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser,
+ int userId) throws IOException, XmlPullParserException {
int outerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1742,10 +2001,10 @@
}
String tagName = parser.getName();
- if (tagName.equals("item")) {
- String name = parser.getAttributeValue(null, "name");
+ if (tagName.equals(TAG_ITEM)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
if (name != null) {
- packageSetting.disabledComponents.add(name.intern());
+ packageSetting.addDisabledComponent(name.intern(), userId);
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <disabled-components> has"
@@ -1759,8 +2018,8 @@
}
}
- private void readEnabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser)
- throws IOException, XmlPullParserException {
+ private void readEnabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser,
+ int userId) throws IOException, XmlPullParserException {
int outerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1770,10 +2029,10 @@
}
String tagName = parser.getName();
- if (tagName.equals("item")) {
- String name = parser.getAttributeValue(null, "name");
+ if (tagName.equals(TAG_ITEM)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
if (name != null) {
- packageSetting.enabledComponents.add(name.intern());
+ packageSetting.addEnabledComponent(name.intern(), userId);
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <enabled-components> has"
@@ -1787,13 +2046,13 @@
}
}
- private void readSharedUserLPw(XmlPullParser parser) throws XmlPullParserException, IOException {
+ private void readSharedUserLPw(XmlPullParser parser) throws XmlPullParserException,IOException {
String name = null;
String idStr = null;
int pkgFlags = 0;
SharedUserSetting su = null;
try {
- name = parser.getAttributeValue(null, "name");
+ name = parser.getAttributeValue(null, ATTR_NAME);
idStr = parser.getAttributeValue(null, "userId");
int userId = idStr != null ? Integer.parseInt(idStr) : 0;
if ("true".equals(parser.getAttributeValue(null, "system"))) {
@@ -1859,8 +2118,8 @@
}
String tagName = parser.getName();
- if (tagName.equals("item")) {
- String name = parser.getAttributeValue(null, "name");
+ if (tagName.equals(TAG_ITEM)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
if (name != null) {
outPerms.add(name.intern());
} else {
@@ -1887,7 +2146,7 @@
}
String tagName = parser.getName();
- if (tagName.equals("item")) {
+ if (tagName.equals(TAG_ITEM)) {
PreferredActivity pa = new PreferredActivity(parser);
if (pa.mPref.getParseError() == null) {
mPreferredActivities.addFilter(pa);
@@ -1940,32 +2199,34 @@
return ps;
}
- boolean isEnabledLPr(ComponentInfo componentInfo, int flags) {
+ boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) {
if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
return true;
}
- final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
+ final String pkgName = componentInfo.packageName;
+ final PackageSetting packageSettings = mPackages.get(pkgName);
if (PackageManagerService.DEBUG_SETTINGS) {
- Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = " + componentInfo.packageName
- + " componentName = " + componentInfo.name);
+ Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = "
+ + componentInfo.packageName + " componentName = " + componentInfo.name);
Log.v(PackageManagerService.TAG, "enabledComponents: "
- + Arrays.toString(packageSettings.enabledComponents.toArray()));
+ + Arrays.toString(packageSettings.getEnabledComponents(userId).toArray()));
Log.v(PackageManagerService.TAG, "disabledComponents: "
- + Arrays.toString(packageSettings.disabledComponents.toArray()));
+ + Arrays.toString(packageSettings.getDisabledComponents(userId).toArray()));
}
if (packageSettings == null) {
return false;
}
- if (packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED
- || packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
+ final int enabled = packageSettings.getEnabled(userId);
+ if (enabled == COMPONENT_ENABLED_STATE_DISABLED
+ || enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
|| (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
- && packageSettings.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
+ && enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
return false;
}
- if (packageSettings.enabledComponents.contains(componentInfo.name)) {
+ if (packageSettings.getEnabledComponents(userId).contains(componentInfo.name)) {
return true;
}
- if (packageSettings.disabledComponents.contains(componentInfo.name)) {
+ if (packageSettings.getDisabledComponents(userId).contains(componentInfo.name)) {
return false;
}
return componentInfo.enabled;
@@ -1979,35 +2240,36 @@
return pkg.installerPackageName;
}
- int getApplicationEnabledSettingLPr(String packageName) {
+ int getApplicationEnabledSettingLPr(String packageName, int userId) {
final PackageSetting pkg = mPackages.get(packageName);
if (pkg == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
- return pkg.enabled;
+ return pkg.getEnabled(userId);
}
- int getComponentEnabledSettingLPr(ComponentName componentName) {
+ int getComponentEnabledSettingLPr(ComponentName componentName, int userId) {
final String packageName = componentName.getPackageName();
final PackageSetting pkg = mPackages.get(packageName);
if (pkg == null) {
throw new IllegalArgumentException("Unknown component: " + componentName);
}
final String classNameStr = componentName.getClassName();
- return pkg.getCurrentEnabledStateLPr(classNameStr);
+ return pkg.getCurrentEnabledStateLPr(classNameStr, userId);
}
-
+
boolean setPackageStoppedStateLPw(String packageName, boolean stopped,
- boolean allowedByPermission, int uid) {
+ boolean allowedByPermission, int uid, int userId) {
+ int appId = UserId.getAppId(uid);
final PackageSetting pkgSetting = mPackages.get(packageName);
if (pkgSetting == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
- if (!allowedByPermission && (uid != pkgSetting.userId)) {
+ if (!allowedByPermission && (appId != pkgSetting.uid)) {
throw new SecurityException(
"Permission Denial: attempt to change stopped state from pid="
+ Binder.getCallingPid()
- + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
+ + ", uid=" + uid + ", package uid=" + pkgSetting.uid);
}
if (DEBUG_STOPPED) {
if (stopped) {
@@ -2016,22 +2278,33 @@
Slog.i(TAG, "Stopping package " + packageName, e);
}
}
- if (pkgSetting.stopped != stopped) {
- pkgSetting.stopped = stopped;
- pkgSetting.pkg.mSetStopped = stopped;
- if (pkgSetting.notLaunched) {
+ if (pkgSetting.getStopped(userId) != stopped) {
+ pkgSetting.setStopped(stopped, userId);
+ // pkgSetting.pkg.mSetStopped = stopped;
+ if (pkgSetting.getNotLaunched(userId)) {
if (pkgSetting.installerPackageName != null) {
PackageManagerService.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
pkgSetting.name, null,
pkgSetting.installerPackageName, null);
}
- pkgSetting.notLaunched = false;
+ pkgSetting.setNotLaunched(false, userId);
}
return true;
}
return false;
}
+ private List<UserInfo> getAllUsers() {
+ try {
+ return AppGlobals.getPackageManager().getUsers();
+ } catch (RemoteException re) {
+ // Local to system process, shouldn't happen
+ } catch (NullPointerException npe) {
+ // packagemanager not yet initialized
+ }
+ return null;
+ }
+
static final void printFlags(PrintWriter pw, int val, Object[] spec) {
pw.print("[ ");
for (int i=0; i<spec.length; i+=2) {
@@ -2096,7 +2369,7 @@
pw.println(ps.name);
}
- pw.print(" userId="); pw.print(ps.userId);
+ pw.print(" userId="); pw.print(ps.uid);
pw.print(" gids="); pw.println(PackageManagerService.arrayToString(ps.gids));
pw.print(" sharedUser="); pw.println(ps.sharedUser);
pw.print(" pkg="); pw.println(ps.pkg);
@@ -2169,18 +2442,24 @@
pw.print(" haveGids="); pw.println(ps.haveGids);
pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
pw.print(" installStatus="); pw.print(ps.installStatus);
- pw.print(" stopped="); pw.print(ps.stopped);
- pw.print(" enabled="); pw.println(ps.enabled);
- if (ps.disabledComponents.size() > 0) {
- pw.println(" disabledComponents:");
- for (String s : ps.disabledComponents) {
- pw.print(" "); pw.println(s);
+ List<UserInfo> users = getAllUsers();
+ for (UserInfo user : users) {
+ pw.print(" User "); pw.print(user.id); pw.print(": ");
+ pw.print(" stopped=");
+ pw.print(ps.getStopped(user.id));
+ pw.print(" enabled=");
+ pw.println(ps.getEnabled(user.id));
+ if (ps.getDisabledComponents(user.id).size() > 0) {
+ pw.println(" disabledComponents:");
+ for (String s : ps.getDisabledComponents(user.id)) {
+ pw.print(" "); pw.println(s);
+ }
}
- }
- if (ps.enabledComponents.size() > 0) {
- pw.println(" enabledComponents:");
- for (String s : ps.enabledComponents) {
- pw.print(" "); pw.println(s);
+ if (ps.getEnabledComponents(user.id).size() > 0) {
+ pw.println(" enabledComponents:");
+ for (String s : ps.getEnabledComponents(user.id)) {
+ pw.print(" "); pw.println(s);
+ }
}
}
if (ps.grantedPermissions.size() > 0) {
@@ -2234,7 +2513,7 @@
pw.println(ps.name);
}
pw.print(" userId=");
- pw.println(ps.userId);
+ pw.println(ps.uid);
pw.print(" sharedUser=");
pw.println(ps.sharedUser);
pw.print(" codePath=");
@@ -2244,7 +2523,7 @@
}
}
}
-
+
void dumpPermissionsLPr(PrintWriter pw, String packageName, DumpState dumpState) {
boolean printedSomething = false;
for (BasePermission p : mPermissions.values()) {
diff --git a/services/java/com/android/server/pm/UserManager.java b/services/java/com/android/server/pm/UserManager.java
index 5eacf4a..959e570 100644
--- a/services/java/com/android/server/pm/UserManager.java
+++ b/services/java/com/android/server/pm/UserManager.java
@@ -73,6 +73,9 @@
UserManager(File dataDir, File baseUserPath) {
mUsersDir = new File(dataDir, USER_INFO_DIR);
mUsersDir.mkdirs();
+ // Make zeroth user directory, for services to migrate their files to that location
+ File userZeroDir = new File(mUsersDir, "0");
+ userZeroDir.mkdirs();
mBaseUserPath = baseUserPath;
FileUtils.setPermissions(mUsersDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index ed83fbe..c2ded8a 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -43,6 +43,7 @@
import android.os.Process;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UEventObserver;
import android.provider.Settings;
@@ -206,6 +207,9 @@
}
private static String addFunction(String functions, String function) {
+ if ("none".equals(functions)) {
+ return function;
+ }
if (!containsFunction(functions, function)) {
if (functions.length() > 0) {
functions += ",";
@@ -222,6 +226,9 @@
split[i] = null;
}
}
+ if (split.length == 1 && split[0] == null) {
+ return "none";
+ }
StringBuilder builder = new StringBuilder();
for (int i = 0; i < split.length; i++) {
String s = split[i];
@@ -365,11 +372,7 @@
for (int i = 0; i < 20; i++) {
// State transition is done when sys.usb.state is set to the new configuration
if (state.equals(SystemProperties.get("sys.usb.state"))) return true;
- try {
- // try again in 50ms
- Thread.sleep(50);
- } catch (InterruptedException e) {
- }
+ SystemClock.sleep(50);
}
Slog.e(TAG, "waitForState(" + state + ") FAILED");
return false;
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index b4fd55e..88ee867 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -53,6 +53,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
+import android.content.pm.UserInfo;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
@@ -69,6 +70,7 @@
import android.os.INetworkManagementService;
import android.os.IPowerManager;
import android.os.MessageQueue.IdleHandler;
+import android.os.UserId;
import android.test.AndroidTestCase;
import android.test.mock.MockPackageManager;
import android.test.suitebuilder.annotation.LargeTest;
@@ -84,7 +86,9 @@
import org.easymock.IAnswer;
import java.io.File;
+import java.util.ArrayList;
import java.util.LinkedHashSet;
+import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@@ -126,8 +130,16 @@
private long mStartTime;
private long mElapsedRealtime;
- private static final int UID_A = android.os.Process.FIRST_APPLICATION_UID + 800;
- private static final int UID_B = android.os.Process.FIRST_APPLICATION_UID + 801;
+ private static final int USER_ID = 0;
+ private static final int USER_ID_GUEST = 1;
+
+ private static final int APP_ID_A = android.os.Process.FIRST_APPLICATION_UID + 800;
+ private static final int APP_ID_B = android.os.Process.FIRST_APPLICATION_UID + 801;
+
+ private static final int UID_A = UserId.getUid(USER_ID, APP_ID_A);
+ private static final int UID_B = UserId.getUid(USER_ID, APP_ID_B);
+ private static final int UID_A_GUEST = UserId.getUid(USER_ID_GUEST, APP_ID_A);
+ private static final int UID_B_GUEST = UserId.getUid(USER_ID_GUEST, APP_ID_B);
private static final int PID_1 = 400;
private static final int PID_2 = 401;
@@ -161,6 +173,14 @@
info.signatures = new Signature[] { signature };
return info;
}
+
+ @Override
+ public List<UserInfo> getUsers() {
+ final ArrayList<UserInfo> users = new ArrayList<UserInfo>();
+ users.add(new UserInfo(USER_ID, "Primary", UserInfo.FLAG_PRIMARY));
+ users.add(new UserInfo(USER_ID_GUEST, "Guest", 0));
+ return users;
+ }
};
}
@@ -242,13 +262,13 @@
@Suppress
public void testPolicyChangeTriggersBroadcast() throws Exception {
- mService.setUidPolicy(UID_A, POLICY_NONE);
+ mService.setAppPolicy(APP_ID_A, POLICY_NONE);
// change background policy and expect broadcast
final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
- mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+ mService.setAppPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
backgroundChanged.get();
}
@@ -302,6 +322,7 @@
public void testScreenChangesRules() throws Exception {
Future<Void> future;
+ Future<Void> futureGuest;
expectSetUidNetworkRules(UID_A, false);
expectSetUidForeground(UID_A, true);
@@ -314,10 +335,14 @@
// push strict policy for foreground uid, verify ALLOW rule
expectSetUidNetworkRules(UID_A, false);
expectSetUidForeground(UID_A, true);
+ expectSetUidNetworkRules(UID_A_GUEST, true);
+ expectSetUidForeground(UID_A_GUEST, false);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ futureGuest = expectRulesChanged(UID_A_GUEST, RULE_REJECT_METERED);
replay();
- mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+ mService.setAppPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
future.get();
+ futureGuest.get();
verifyAndReset();
// now turn screen off and verify REJECT rule
@@ -343,6 +368,7 @@
public void testPolicyNone() throws Exception {
Future<Void> future;
+ Future<Void> futureGuest;
expectSetUidNetworkRules(UID_A, false);
expectSetUidForeground(UID_A, true);
@@ -355,10 +381,14 @@
// POLICY_NONE should RULE_ALLOW in foreground
expectSetUidNetworkRules(UID_A, false);
expectSetUidForeground(UID_A, true);
+ expectSetUidNetworkRules(UID_A_GUEST, false);
+ expectSetUidForeground(UID_A_GUEST, false);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ futureGuest = expectRulesChanged(UID_A_GUEST, RULE_ALLOW_ALL);
replay();
- mService.setUidPolicy(UID_A, POLICY_NONE);
+ mService.setAppPolicy(APP_ID_A, POLICY_NONE);
future.get();
+ futureGuest.get();
verifyAndReset();
// POLICY_NONE should RULE_ALLOW in background
@@ -373,14 +403,19 @@
public void testPolicyReject() throws Exception {
Future<Void> future;
+ Future<Void> futureGuest;
// POLICY_REJECT should RULE_ALLOW in background
expectSetUidNetworkRules(UID_A, true);
expectSetUidForeground(UID_A, false);
+ expectSetUidNetworkRules(UID_A_GUEST, true);
+ expectSetUidForeground(UID_A_GUEST, false);
future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
+ futureGuest = expectRulesChanged(UID_A_GUEST, RULE_REJECT_METERED);
replay();
- mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+ mService.setAppPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
future.get();
+ futureGuest.get();
verifyAndReset();
// POLICY_REJECT should RULE_ALLOW in foreground
@@ -404,33 +439,46 @@
public void testPolicyRejectAddRemove() throws Exception {
Future<Void> future;
+ Future<Void> futureGuest;
// POLICY_NONE should have RULE_ALLOW in background
expectSetUidNetworkRules(UID_A, false);
expectSetUidForeground(UID_A, false);
+ expectSetUidNetworkRules(UID_A_GUEST, false);
+ expectSetUidForeground(UID_A_GUEST, false);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ futureGuest = expectRulesChanged(UID_A_GUEST, RULE_ALLOW_ALL);
replay();
mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- mService.setUidPolicy(UID_A, POLICY_NONE);
+ mService.setAppPolicy(APP_ID_A, POLICY_NONE);
future.get();
+ futureGuest.get();
verifyAndReset();
// adding POLICY_REJECT should cause RULE_REJECT
expectSetUidNetworkRules(UID_A, true);
expectSetUidForeground(UID_A, false);
+ expectSetUidNetworkRules(UID_A_GUEST, true);
+ expectSetUidForeground(UID_A_GUEST, false);
future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
+ futureGuest = expectRulesChanged(UID_A_GUEST, RULE_REJECT_METERED);
replay();
- mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+ mService.setAppPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
future.get();
+ futureGuest.get();
verifyAndReset();
// removing POLICY_REJECT should return us to RULE_ALLOW
expectSetUidNetworkRules(UID_A, false);
expectSetUidForeground(UID_A, false);
+ expectSetUidNetworkRules(UID_A_GUEST, false);
+ expectSetUidForeground(UID_A_GUEST, false);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ futureGuest = expectRulesChanged(UID_A_GUEST, RULE_ALLOW_ALL);
replay();
- mService.setUidPolicy(UID_A, POLICY_NONE);
+ mService.setAppPolicy(APP_ID_A, POLICY_NONE);
future.get();
+ futureGuest.get();
verifyAndReset();
}
@@ -599,25 +647,34 @@
public void testUidRemovedPolicyCleared() throws Exception {
Future<Void> future;
+ Future<Void> futureGuest;
// POLICY_REJECT should RULE_REJECT in background
expectSetUidNetworkRules(UID_A, true);
expectSetUidForeground(UID_A, false);
+ expectSetUidNetworkRules(UID_A_GUEST, true);
+ expectSetUidForeground(UID_A_GUEST, false);
future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
+ futureGuest = expectRulesChanged(UID_A_GUEST, RULE_REJECT_METERED);
replay();
- mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+ mService.setAppPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
future.get();
+ futureGuest.get();
verifyAndReset();
// uninstall should clear RULE_REJECT
expectSetUidNetworkRules(UID_A, false);
expectSetUidForeground(UID_A, false);
+ expectSetUidNetworkRules(UID_A_GUEST, false);
+ expectSetUidForeground(UID_A_GUEST, false);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ futureGuest = expectRulesChanged(UID_A_GUEST, RULE_ALLOW_ALL);
replay();
final Intent intent = new Intent(ACTION_UID_REMOVED);
intent.putExtra(EXTRA_UID, UID_A);
mServiceContext.sendBroadcast(intent);
future.get();
+ futureGuest.get();
verifyAndReset();
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
new file mode 100644
index 0000000..796372d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+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_DISABLED_USER;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+
+import com.android.internal.content.PackageHelper;
+import com.android.internal.os.AtomicFile;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.HashSet;
+
+import android.os.Debug;
+import android.os.Environment;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.storage.IMountService;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+public class PackageManagerSettingsTests extends AndroidTestCase {
+
+ private static final String PACKAGE_NAME_2 = "com.google.app2";
+ private static final String PACKAGE_NAME_3 = "com.android.app3";
+ private static final String PACKAGE_NAME_1 = "com.google.app1";
+ private static final boolean localLOGV = true;
+ public static final String TAG = "PackageManagerSettingsTests";
+ protected final String PREFIX = "android.content.pm";
+
+ private void writeFile(File file, byte[] data) {
+ file.mkdirs();
+ try {
+ AtomicFile aFile = new AtomicFile(file);
+ FileOutputStream fos = aFile.startWrite();
+ fos.write(data);
+ aFile.finishWrite(fos);
+ } catch (IOException ioe) {
+ Log.e(TAG, "Cannot write file " + file.getPath());
+ }
+ }
+
+ private void writePackagesXml() {
+ writeFile(new File(getContext().getFilesDir(), "system/packages.xml"),
+ ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
+ + "<packages>"
+ + "<last-platform-version internal=\"15\" external=\"0\" />"
+ + "<permission-trees>"
+ + "<item name=\"com.google.android.permtree\" package=\"com.google.android.permpackage\" />"
+ + "</permission-trees>"
+ + "<permissions>"
+ + "<item name=\"android.permission.WRITE_CALL_LOG\" package=\"android\" protection=\"1\" />"
+ + "<item name=\"android.permission.ASEC_ACCESS\" package=\"android\" protection=\"2\" />"
+ + "<item name=\"android.permission.ACCESS_WIMAX_STATE\" package=\"android\" />"
+ + "<item name=\"android.permission.REBOOT\" package=\"android\" protection=\"18\" />"
+ + "</permissions>"
+ + "<package name=\"com.google.app1\" codePath=\"/system/app/app1.apk\" nativeLibraryPath=\"/data/data/com.google.app1/lib\" flags=\"1\" ft=\"1360e2caa70\" it=\"135f2f80d08\" ut=\"1360e2caa70\" version=\"1109\" sharedUserId=\"11000\">"
+ + "<sigs count=\"1\">"
+ + "<cert index=\"0\" key=\"308886\" />"
+ + "</sigs>"
+ + "</package>"
+ + "<package name=\"com.google.app2\" codePath=\"/system/app/app2.apk\" nativeLibraryPath=\"/data/data/com.google.app2/lib\" flags=\"1\" ft=\"1360e578718\" it=\"135f2f80d08\" ut=\"1360e578718\" version=\"15\" enabled=\"3\" userId=\"11001\">"
+ + "<sigs count=\"1\">"
+ + "<cert index=\"0\" />"
+ + "</sigs>"
+ + "</package>"
+ + "<package name=\"com.android.app3\" codePath=\"/system/app/app3.apk\" nativeLibraryPath=\"/data/data/com.android.app3/lib\" flags=\"1\" ft=\"1360e577b60\" it=\"135f2f80d08\" ut=\"1360e577b60\" version=\"15\" userId=\"11030\">"
+ + "<sigs count=\"1\">"
+ + "<cert index=\"1\" key=\"308366\" />"
+ + "</sigs>"
+ + "</package>"
+ + "<shared-user name=\"com.android.shared1\" userId=\"11000\">"
+ + "<sigs count=\"1\">"
+ + "<cert index=\"1\" />"
+ + "</sigs>"
+ + "<perms>"
+ + "<item name=\"android.permission.REBOOT\" />"
+ + "</perms>"
+ + "</shared-user>"
+ + "</packages>").getBytes());
+ }
+
+ private void writeStoppedPackagesXml() {
+ writeFile(new File(getContext().getFilesDir(), "system/packages-stopped.xml"),
+ ( "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
+ + "<stopped-packages>"
+ + "<pkg name=\"com.google.app1\" nl=\"1\" />"
+ + "<pkg name=\"com.android.app3\" nl=\"1\" />"
+ + "</stopped-packages>")
+ .getBytes());
+ }
+
+ private void writePackagesList() {
+ writeFile(new File(getContext().getFilesDir(), "system/packages.list"),
+ ( "com.google.app1 11000 0 /data/data/com.google.app1"
+ + "com.google.app2 11001 0 /data/data/com.google.app2"
+ + "com.android.app3 11030 0 /data/data/com.android.app3")
+ .getBytes());
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ private void writeOldFiles() {
+ writePackagesXml();
+ writeStoppedPackagesXml();
+ writePackagesList();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testSettingsReadOld() {
+ // Debug.waitForDebugger();
+
+ // Write the package files and make sure they're parsed properly the first time
+ writeOldFiles();
+ Settings settings = new Settings(getContext().getFilesDir());
+ assertEquals(true, settings.readLPw(null));
+ assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_3));
+ assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_1));
+
+ PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_1);
+ assertEquals(COMPONENT_ENABLED_STATE_DEFAULT, ps.getEnabled(0));
+ assertEquals(true, ps.getNotLaunched(0));
+
+ ps = settings.peekPackageLPr(PACKAGE_NAME_2);
+ assertEquals(false, ps.getStopped(0));
+ assertEquals(COMPONENT_ENABLED_STATE_DISABLED_USER, ps.getEnabled(0));
+ assertEquals(COMPONENT_ENABLED_STATE_DEFAULT, ps.getEnabled(1));
+ }
+
+ public void testNewPackageRestrictionsFile() {
+ // Write the package files and make sure they're parsed properly the first time
+ writeOldFiles();
+ Settings settings = new Settings(getContext().getFilesDir());
+ assertEquals(true, settings.readLPw(null));
+
+ // Create Settings again to make it read from the new files
+ settings = new Settings(getContext().getFilesDir());
+ assertEquals(true, settings.readLPw(null));
+
+ PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_2);
+ assertEquals(COMPONENT_ENABLED_STATE_DISABLED_USER, ps.getEnabled(0));
+ assertEquals(COMPONENT_ENABLED_STATE_DEFAULT, ps.getEnabled(1));
+ }
+
+ public void testEnableDisable() {
+ // Write the package files and make sure they're parsed properly the first time
+ writeOldFiles();
+ Settings settings = new Settings(getContext().getFilesDir());
+ assertEquals(true, settings.readLPw(null));
+
+ // Enable/Disable a package
+ PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_1);
+ ps.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0);
+ ps.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 1);
+ assertEquals(COMPONENT_ENABLED_STATE_DISABLED, ps.getEnabled(0));
+ assertEquals(COMPONENT_ENABLED_STATE_ENABLED, ps.getEnabled(1));
+
+ // Enable/Disable a component
+ HashSet<String> components = new HashSet<String>();
+ String component1 = PACKAGE_NAME_1 + "/.Component1";
+ components.add(component1);
+ ps.setDisabledComponents(components, 0);
+ HashSet<String> componentsDisabled = ps.getDisabledComponents(0);
+ assertEquals(1, componentsDisabled.size());
+ assertEquals(component1, componentsDisabled.toArray()[0]);
+ boolean hasEnabled =
+ ps.getEnabledComponents(0) != null && ps.getEnabledComponents(1).size() > 0;
+ assertEquals(false, hasEnabled);
+
+ // User 1 should not have any disabled components
+ boolean hasDisabled =
+ ps.getDisabledComponents(1) != null && ps.getDisabledComponents(1).size() > 0;
+ assertEquals(false, hasDisabled);
+ ps.setEnabledComponents(components, 1);
+ assertEquals(1, ps.getEnabledComponents(1).size());
+ hasEnabled = ps.getEnabledComponents(0) != null && ps.getEnabledComponents(0).size() > 0;
+ assertEquals(false, hasEnabled);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index 7ae6692..2139917 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -37,6 +37,7 @@
import com.android.internal.telephony.CommandsInterface.RadioState;
import com.android.internal.telephony.gsm.SIMFileHandler;
import com.android.internal.telephony.gsm.SIMRecords;
+import com.android.internal.telephony.cat.CatService;
import com.android.internal.telephony.cdma.CDMALTEPhone;
import com.android.internal.telephony.cdma.CdmaLteUiccFileHandler;
import com.android.internal.telephony.cdma.CdmaLteUiccRecords;
@@ -65,6 +66,8 @@
protected PhoneBase mPhone;
private IccRecords mIccRecords;
private IccFileHandler mIccFileHandler;
+ private CatService mCatService;
+
private RegistrantList mAbsentRegistrants = new RegistrantList();
private RegistrantList mPinLockedRegistrants = new RegistrantList();
private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
@@ -194,6 +197,8 @@
mIccRecords = is3gpp ? new SIMRecords(this, mPhone.mContext, mPhone.mCM) :
new RuimRecords(this, mPhone.mContext, mPhone.mCM);
}
+ mCatService = CatService.getInstance(mPhone.mCM, mIccRecords,
+ mPhone.mContext, mIccFileHandler, this);
mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mPhone.mCM.registerForOn(mHandler, EVENT_RADIO_ON, null);
mPhone.mCM.registerForIccStatusChanged(mHandler, EVENT_ICC_STATUS_CHANGED, null);
@@ -204,6 +209,7 @@
mPhone.mCM.unregisterForIccStatusChanged(mHandler);
mPhone.mCM.unregisterForOffOrNotAvailable(mHandler);
mPhone.mCM.unregisterForOn(mHandler);
+ mCatService.dispose();
mCdmaSSM.dispose(mHandler);
mIccRecords.dispose();
mIccFileHandler.dispose();
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 9e4a735..ce581de 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -103,7 +103,6 @@
PhoneSubInfo mSubInfo;
EriManager mEriManager;
WakeLock mWakeLock;
- CatService mCcatService;
// mEriFileLoadedRegistrants are informed after the ERI text has been loaded
private final RegistrantList mEriFileLoadedRegistrants = new RegistrantList();
@@ -169,8 +168,6 @@
mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this, mSMS);
mSubInfo = new PhoneSubInfo(this);
mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
- mCcatService = CatService.getInstance(mCM, mIccRecords, mContext,
- mIccFileHandler, mIccCard);
mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
registerForRuimRecordEvents();
@@ -245,14 +242,12 @@
mRuimSmsInterfaceManager.dispose();
mSubInfo.dispose();
mEriManager.dispose();
- mCcatService.dispose();
}
}
@Override
public void removeReferences() {
log("removeReferences");
- super.removeReferences();
mRuimPhoneBookInterfaceManager = null;
mRuimSmsInterfaceManager = null;
mSubInfo = null;
@@ -260,8 +255,8 @@
mCT = null;
mSST = null;
mEriManager = null;
- mCcatService = null;
mExitEcmRunnable = null;
+ super.removeReferences();
}
@Override
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index 27f362c..6e10542 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -101,7 +101,6 @@
// Instance Variables
GsmCallTracker mCT;
GsmServiceStateTracker mSST;
- CatService mStkService;
ArrayList <GsmMmiCode> mPendingMMIs = new ArrayList<GsmMmiCode>();
SimPhoneBookInterfaceManager mSimPhoneBookIntManager;
SimSmsInterfaceManager mSimSmsIntManager;
@@ -149,7 +148,6 @@
mSimSmsIntManager = new SimSmsInterfaceManager(this, mSMS);
mSubInfo = new PhoneSubInfo(this);
}
- mStkService = CatService.getInstance(mCM, mIccRecords, mContext, mIccFileHandler, mIccCard);
mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
registerForSimRecordEvents();
@@ -215,7 +213,6 @@
mPendingMMIs.clear();
//Force all referenced classes to unregister their former registered events
- mStkService.dispose();
mCT.dispose();
mDataConnectionTracker.dispose();
mSST.dispose();
@@ -228,15 +225,14 @@
@Override
public void removeReferences() {
Log.d(LOG_TAG, "removeReferences");
- super.removeReferences();
mSimulatedRadioControl = null;
- mStkService = null;
mSimPhoneBookIntManager = null;
mSimSmsIntManager = null;
mSubInfo = null;
mIccFileHandler = null;
mCT = null;
mSST = null;
+ super.removeReferences();
}
protected void finalize() {
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs
index 11b8c30..0eaca4a 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs
@@ -7,11 +7,11 @@
static bool test_program_raster_getters() {
bool failed = false;
- _RS_ASSERT(rsgProgramRasterGetPointSpriteEnabled(pointSpriteEnabled) == true);
- _RS_ASSERT(rsgProgramRasterGetCullMode(pointSpriteEnabled) == RS_CULL_BACK);
+ _RS_ASSERT(rsProgramRasterGetPointSpriteEnabled(pointSpriteEnabled) == true);
+ _RS_ASSERT(rsProgramRasterGetCullMode(pointSpriteEnabled) == RS_CULL_BACK);
- _RS_ASSERT(rsgProgramRasterGetPointSpriteEnabled(cullMode) == false);
- _RS_ASSERT(rsgProgramRasterGetCullMode(cullMode) == RS_CULL_FRONT);
+ _RS_ASSERT(rsProgramRasterGetPointSpriteEnabled(cullMode) == false);
+ _RS_ASSERT(rsProgramRasterGetCullMode(cullMode) == RS_CULL_FRONT);
if (failed) {
rsDebug("test_program_raster_getters FAILED", 0);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs
index 3cd8a20..7b47408 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs
@@ -14,95 +14,95 @@
static bool test_program_store_getters() {
bool failed = false;
- _RS_ASSERT(rsgProgramStoreGetDepthFunc(depthFunc) == RS_DEPTH_FUNC_GREATER);
- _RS_ASSERT(rsgProgramStoreGetDepthMask(depthFunc) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskR(depthFunc) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskG(depthFunc) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskB(depthFunc) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskA(depthFunc) == false);
- _RS_ASSERT(rsgProgramStoreGetDitherEnabled(depthFunc) == false);
- _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(depthFunc) == RS_BLEND_SRC_ZERO);
- _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(depthFunc) == RS_BLEND_DST_ZERO);
+ _RS_ASSERT(rsProgramStoreGetDepthFunc(depthFunc) == RS_DEPTH_FUNC_GREATER);
+ _RS_ASSERT(rsProgramStoreGetDepthMask(depthFunc) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskR(depthFunc) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskG(depthFunc) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskB(depthFunc) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskA(depthFunc) == false);
+ _RS_ASSERT(rsProgramStoreGetDitherEnabled(depthFunc) == false);
+ _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(depthFunc) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsProgramStoreGetBlendDstFunc(depthFunc) == RS_BLEND_DST_ZERO);
- _RS_ASSERT(rsgProgramStoreGetDepthFunc(depthWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
- _RS_ASSERT(rsgProgramStoreGetDepthMask(depthWriteEnable) == true);
- _RS_ASSERT(rsgProgramStoreGetColorMaskR(depthWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskG(depthWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskB(depthWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskA(depthWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetDitherEnabled(depthWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(depthWriteEnable) == RS_BLEND_SRC_ZERO);
- _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(depthWriteEnable) == RS_BLEND_DST_ZERO);
+ _RS_ASSERT(rsProgramStoreGetDepthFunc(depthWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsProgramStoreGetDepthMask(depthWriteEnable) == true);
+ _RS_ASSERT(rsProgramStoreGetColorMaskR(depthWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskG(depthWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskB(depthWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskA(depthWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetDitherEnabled(depthWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(depthWriteEnable) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsProgramStoreGetBlendDstFunc(depthWriteEnable) == RS_BLEND_DST_ZERO);
- _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorRWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
- _RS_ASSERT(rsgProgramStoreGetDepthMask(colorRWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorRWriteEnable) == true);
- _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorRWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorRWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorRWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorRWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorRWriteEnable) == RS_BLEND_SRC_ZERO);
- _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorRWriteEnable) == RS_BLEND_DST_ZERO);
+ _RS_ASSERT(rsProgramStoreGetDepthFunc(colorRWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsProgramStoreGetDepthMask(colorRWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskR(colorRWriteEnable) == true);
+ _RS_ASSERT(rsProgramStoreGetColorMaskG(colorRWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskB(colorRWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskA(colorRWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetDitherEnabled(colorRWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(colorRWriteEnable) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsProgramStoreGetBlendDstFunc(colorRWriteEnable) == RS_BLEND_DST_ZERO);
- _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorGWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
- _RS_ASSERT(rsgProgramStoreGetDepthMask(colorGWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorGWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorGWriteEnable) == true);
- _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorGWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorGWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorGWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorGWriteEnable) == RS_BLEND_SRC_ZERO);
- _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorGWriteEnable) == RS_BLEND_DST_ZERO);
+ _RS_ASSERT(rsProgramStoreGetDepthFunc(colorGWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsProgramStoreGetDepthMask(colorGWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskR(colorGWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskG(colorGWriteEnable) == true);
+ _RS_ASSERT(rsProgramStoreGetColorMaskB(colorGWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskA(colorGWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetDitherEnabled(colorGWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(colorGWriteEnable) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsProgramStoreGetBlendDstFunc(colorGWriteEnable) == RS_BLEND_DST_ZERO);
- _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorBWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
- _RS_ASSERT(rsgProgramStoreGetDepthMask(colorBWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorBWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorBWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorBWriteEnable) == true);
- _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorBWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorBWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorBWriteEnable) == RS_BLEND_SRC_ZERO);
- _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorBWriteEnable) == RS_BLEND_DST_ZERO);
+ _RS_ASSERT(rsProgramStoreGetDepthFunc(colorBWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsProgramStoreGetDepthMask(colorBWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskR(colorBWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskG(colorBWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskB(colorBWriteEnable) == true);
+ _RS_ASSERT(rsProgramStoreGetColorMaskA(colorBWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetDitherEnabled(colorBWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(colorBWriteEnable) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsProgramStoreGetBlendDstFunc(colorBWriteEnable) == RS_BLEND_DST_ZERO);
- _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorAWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
- _RS_ASSERT(rsgProgramStoreGetDepthMask(colorAWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorAWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorAWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorAWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorAWriteEnable) == true);
- _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorAWriteEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorAWriteEnable) == RS_BLEND_SRC_ZERO);
- _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorAWriteEnable) == RS_BLEND_DST_ZERO);
+ _RS_ASSERT(rsProgramStoreGetDepthFunc(colorAWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsProgramStoreGetDepthMask(colorAWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskR(colorAWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskG(colorAWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskB(colorAWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskA(colorAWriteEnable) == true);
+ _RS_ASSERT(rsProgramStoreGetDitherEnabled(colorAWriteEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(colorAWriteEnable) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsProgramStoreGetBlendDstFunc(colorAWriteEnable) == RS_BLEND_DST_ZERO);
- _RS_ASSERT(rsgProgramStoreGetDepthFunc(ditherEnable) == RS_DEPTH_FUNC_ALWAYS);
- _RS_ASSERT(rsgProgramStoreGetDepthMask(ditherEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskR(ditherEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskG(ditherEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskB(ditherEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskA(ditherEnable) == false);
- _RS_ASSERT(rsgProgramStoreGetDitherEnabled(ditherEnable) == true);
- _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(ditherEnable) == RS_BLEND_SRC_ZERO);
- _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(ditherEnable) == RS_BLEND_DST_ZERO);
+ _RS_ASSERT(rsProgramStoreGetDepthFunc(ditherEnable) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsProgramStoreGetDepthMask(ditherEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskR(ditherEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskG(ditherEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskB(ditherEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskA(ditherEnable) == false);
+ _RS_ASSERT(rsProgramStoreGetDitherEnabled(ditherEnable) == true);
+ _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(ditherEnable) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsProgramStoreGetBlendDstFunc(ditherEnable) == RS_BLEND_DST_ZERO);
- _RS_ASSERT(rsgProgramStoreGetDepthFunc(blendSrc) == RS_DEPTH_FUNC_ALWAYS);
- _RS_ASSERT(rsgProgramStoreGetDepthMask(blendSrc) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskR(blendSrc) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskG(blendSrc) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskB(blendSrc) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskA(blendSrc) == false);
- _RS_ASSERT(rsgProgramStoreGetDitherEnabled(blendSrc) == false);
- _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(blendSrc) == RS_BLEND_SRC_DST_COLOR);
- _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(blendSrc) == RS_BLEND_DST_ZERO);
+ _RS_ASSERT(rsProgramStoreGetDepthFunc(blendSrc) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsProgramStoreGetDepthMask(blendSrc) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskR(blendSrc) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskG(blendSrc) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskB(blendSrc) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskA(blendSrc) == false);
+ _RS_ASSERT(rsProgramStoreGetDitherEnabled(blendSrc) == false);
+ _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(blendSrc) == RS_BLEND_SRC_DST_COLOR);
+ _RS_ASSERT(rsProgramStoreGetBlendDstFunc(blendSrc) == RS_BLEND_DST_ZERO);
- _RS_ASSERT(rsgProgramStoreGetDepthFunc(blendDst) == RS_DEPTH_FUNC_ALWAYS);
- _RS_ASSERT(rsgProgramStoreGetDepthMask(blendDst) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskR(blendDst) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskG(blendDst) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskB(blendDst) == false);
- _RS_ASSERT(rsgProgramStoreGetColorMaskA(blendDst) == false);
- _RS_ASSERT(rsgProgramStoreGetDitherEnabled(blendDst) == false);
- _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(blendDst) == RS_BLEND_SRC_ZERO);
- _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(blendDst) == RS_BLEND_DST_DST_ALPHA);
+ _RS_ASSERT(rsProgramStoreGetDepthFunc(blendDst) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsProgramStoreGetDepthMask(blendDst) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskR(blendDst) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskG(blendDst) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskB(blendDst) == false);
+ _RS_ASSERT(rsProgramStoreGetColorMaskA(blendDst) == false);
+ _RS_ASSERT(rsProgramStoreGetDitherEnabled(blendDst) == false);
+ _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(blendDst) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsProgramStoreGetBlendDstFunc(blendDst) == RS_BLEND_DST_DST_ALPHA);
if (failed) {
rsDebug("test_program_store_getters FAILED", 0);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/sampler.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/sampler.rs
index ac9a549..ff1c0a7 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/sampler.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/sampler.rs
@@ -9,35 +9,35 @@
static bool test_sampler_getters() {
bool failed = false;
- _RS_ASSERT(rsgSamplerGetMagnification(minification) == RS_SAMPLER_NEAREST);
- _RS_ASSERT(rsgSamplerGetMinification(minification) == RS_SAMPLER_LINEAR_MIP_LINEAR);
- _RS_ASSERT(rsgSamplerGetWrapS(minification) == RS_SAMPLER_CLAMP);
- _RS_ASSERT(rsgSamplerGetWrapT(minification) == RS_SAMPLER_CLAMP);
- _RS_ASSERT(rsgSamplerGetAnisotropy(minification) == 1.0f);
+ _RS_ASSERT(rsSamplerGetMagnification(minification) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsSamplerGetMinification(minification) == RS_SAMPLER_LINEAR_MIP_LINEAR);
+ _RS_ASSERT(rsSamplerGetWrapS(minification) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsSamplerGetWrapT(minification) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsSamplerGetAnisotropy(minification) == 1.0f);
- _RS_ASSERT(rsgSamplerGetMagnification(magnification) == RS_SAMPLER_LINEAR);
- _RS_ASSERT(rsgSamplerGetMinification(magnification) == RS_SAMPLER_NEAREST);
- _RS_ASSERT(rsgSamplerGetWrapS(magnification) == RS_SAMPLER_CLAMP);
- _RS_ASSERT(rsgSamplerGetWrapT(magnification) == RS_SAMPLER_CLAMP);
- _RS_ASSERT(rsgSamplerGetAnisotropy(magnification) == 1.0f);
+ _RS_ASSERT(rsSamplerGetMagnification(magnification) == RS_SAMPLER_LINEAR);
+ _RS_ASSERT(rsSamplerGetMinification(magnification) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsSamplerGetWrapS(magnification) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsSamplerGetWrapT(magnification) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsSamplerGetAnisotropy(magnification) == 1.0f);
- _RS_ASSERT(rsgSamplerGetMagnification(wrapS) == RS_SAMPLER_NEAREST);
- _RS_ASSERT(rsgSamplerGetMinification(wrapS) == RS_SAMPLER_NEAREST);
- _RS_ASSERT(rsgSamplerGetWrapS(wrapS) == RS_SAMPLER_WRAP);
- _RS_ASSERT(rsgSamplerGetWrapT(wrapS) == RS_SAMPLER_CLAMP);
- _RS_ASSERT(rsgSamplerGetAnisotropy(wrapS) == 1.0f);
+ _RS_ASSERT(rsSamplerGetMagnification(wrapS) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsSamplerGetMinification(wrapS) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsSamplerGetWrapS(wrapS) == RS_SAMPLER_WRAP);
+ _RS_ASSERT(rsSamplerGetWrapT(wrapS) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsSamplerGetAnisotropy(wrapS) == 1.0f);
- _RS_ASSERT(rsgSamplerGetMagnification(wrapT) == RS_SAMPLER_NEAREST);
- _RS_ASSERT(rsgSamplerGetMinification(wrapT) == RS_SAMPLER_NEAREST);
- _RS_ASSERT(rsgSamplerGetWrapS(wrapT) == RS_SAMPLER_CLAMP);
- _RS_ASSERT(rsgSamplerGetWrapT(wrapT) == RS_SAMPLER_WRAP);
- _RS_ASSERT(rsgSamplerGetAnisotropy(wrapT) == 1.0f);
+ _RS_ASSERT(rsSamplerGetMagnification(wrapT) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsSamplerGetMinification(wrapT) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsSamplerGetWrapS(wrapT) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsSamplerGetWrapT(wrapT) == RS_SAMPLER_WRAP);
+ _RS_ASSERT(rsSamplerGetAnisotropy(wrapT) == 1.0f);
- _RS_ASSERT(rsgSamplerGetMagnification(anisotropy) == RS_SAMPLER_NEAREST);
- _RS_ASSERT(rsgSamplerGetMinification(anisotropy) == RS_SAMPLER_NEAREST);
- _RS_ASSERT(rsgSamplerGetWrapS(anisotropy) == RS_SAMPLER_CLAMP);
- _RS_ASSERT(rsgSamplerGetWrapT(anisotropy) == RS_SAMPLER_CLAMP);
- _RS_ASSERT(rsgSamplerGetAnisotropy(anisotropy) == 8.0f);
+ _RS_ASSERT(rsSamplerGetMagnification(anisotropy) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsSamplerGetMinification(anisotropy) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsSamplerGetWrapS(anisotropy) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsSamplerGetWrapT(anisotropy) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsSamplerGetAnisotropy(anisotropy) == 8.0f);
if (failed) {
rsDebug("test_sampler_getters FAILED", 0);
diff --git a/wifi/java/android/net/wifi/NetworkUpdateResult.java b/wifi/java/android/net/wifi/NetworkUpdateResult.java
index 6b7b68b..234bbe1 100644
--- a/wifi/java/android/net/wifi/NetworkUpdateResult.java
+++ b/wifi/java/android/net/wifi/NetworkUpdateResult.java
@@ -22,6 +22,7 @@
int netId;
boolean ipChanged;
boolean proxyChanged;
+ boolean isNewNetwork = false;
public NetworkUpdateResult(int id) {
netId = id;
@@ -58,4 +59,12 @@
public boolean hasProxyChanged() {
return proxyChanged;
}
+
+ public boolean isNewNetwork() {
+ return isNewNetwork;
+ }
+
+ public void setIsNewNetwork(boolean isNew) {
+ isNewNetwork = isNew;
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 46ad036..5dec269 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -273,7 +273,8 @@
mConfiguredNetworks.get(netId).status = Status.ENABLED;
}
mWifiNative.saveConfig();
- sendConfiguredNetworksChangedBroadcast();
+ sendConfiguredNetworksChangedBroadcast(config, result.isNewNetwork() ?
+ WifiManager.CHANGE_REASON_ADDED : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
return result;
}
@@ -307,13 +308,16 @@
boolean forgetNetwork(int netId) {
if (mWifiNative.removeNetwork(netId)) {
mWifiNative.saveConfig();
+ WifiConfiguration target = null;
WifiConfiguration config = mConfiguredNetworks.get(netId);
if (config != null) {
- mConfiguredNetworks.remove(netId);
+ target = mConfiguredNetworks.remove(netId);
mNetworkIds.remove(configKey(config));
}
- writeIpAndProxyConfigurations();
- sendConfiguredNetworksChangedBroadcast();
+ if (target != null) {
+ writeIpAndProxyConfigurations();
+ sendConfiguredNetworksChangedBroadcast(target, WifiManager.CHANGE_REASON_REMOVED);
+ }
return true;
} else {
loge("Failed to remove network " + netId);
@@ -332,7 +336,11 @@
*/
int addOrUpdateNetwork(WifiConfiguration config) {
NetworkUpdateResult result = addOrUpdateNetworkNative(config);
- sendConfiguredNetworksChangedBroadcast();
+ if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
+ sendConfiguredNetworksChangedBroadcast(mConfiguredNetworks.get(result.getNetworkId()),
+ result.isNewNetwork ? WifiManager.CHANGE_REASON_ADDED :
+ WifiManager.CHANGE_REASON_CONFIG_CHANGE);
+ }
return result.getNetworkId();
}
@@ -347,14 +355,17 @@
*/
boolean removeNetwork(int netId) {
boolean ret = mWifiNative.removeNetwork(netId);
+ WifiConfiguration config = null;
if (ret) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
+ config = mConfiguredNetworks.get(netId);
if (config != null) {
- mConfiguredNetworks.remove(netId);
+ config = mConfiguredNetworks.remove(netId);
mNetworkIds.remove(configKey(config));
}
}
- sendConfiguredNetworksChangedBroadcast();
+ if (config != null) {
+ sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_REMOVED);
+ }
return ret;
}
@@ -364,12 +375,24 @@
* API. The more powerful selectNetwork()/saveNetwork() is used by the
* state machine for connecting to a network
*
- * @param netId network to be removed
+ * @param netId network to be enabled
* @return {@code true} if it succeeds, {@code false} otherwise
*/
boolean enableNetwork(int netId, boolean disableOthers) {
boolean ret = enableNetworkWithoutBroadcast(netId, disableOthers);
- sendConfiguredNetworksChangedBroadcast();
+ if (disableOthers) {
+ sendConfiguredNetworksChangedBroadcast();
+ } else {
+ WifiConfiguration enabledNetwork = null;
+ synchronized(mConfiguredNetworks) {
+ enabledNetwork = mConfiguredNetworks.get(netId);
+ }
+ // check just in case the network was removed by someone else.
+ if (enabledNetwork != null) {
+ sendConfiguredNetworksChangedBroadcast(enabledNetwork,
+ WifiManager.CHANGE_REASON_CONFIG_CHANGE);
+ }
+ }
return ret;
}
@@ -402,13 +425,18 @@
*/
boolean disableNetwork(int netId, int reason) {
boolean ret = mWifiNative.disableNetwork(netId);
+ WifiConfiguration network = null;
WifiConfiguration config = mConfiguredNetworks.get(netId);
/* Only change the reason if the network was not previously disabled */
if (config != null && config.status != Status.DISABLED) {
config.status = Status.DISABLED;
config.disableReason = reason;
+ network = config;
}
- sendConfiguredNetworksChangedBroadcast();
+ if (network != null) {
+ sendConfiguredNetworksChangedBroadcast(network,
+ WifiManager.CHANGE_REASON_CONFIG_CHANGE);
+ }
return ret;
}
@@ -574,9 +602,29 @@
return false;
}
+ /**
+ * Should be called when a single network configuration is made.
+ * @param network The network configuration that changed.
+ * @param reason The reason for the change, should be one of WifiManager.CHANGE_REASON_ADDED,
+ * WifiManager.CHANGE_REASON_REMOVED, or WifiManager.CHANGE_REASON_CHANGE.
+ */
+ private void sendConfiguredNetworksChangedBroadcast(WifiConfiguration network,
+ int reason) {
+ Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, false);
+ intent.putExtra(WifiManager.EXTRA_WIFI_CONFIGURATION, network);
+ intent.putExtra(WifiManager.EXTRA_CHANGE_REASON, reason);
+ mContext.sendBroadcast(intent);
+ }
+
+ /**
+ * Should be called when multiple network configuration changes are made.
+ */
private void sendConfiguredNetworksChangedBroadcast() {
Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, true);
mContext.sendBroadcast(intent);
}
@@ -1135,6 +1183,7 @@
mNetworkIds.put(configKey(currentConfig), netId);
NetworkUpdateResult result = writeIpAndProxyConfigurationsOnChange(currentConfig, config);
+ result.setIsNewNetwork(newNetwork);
result.setNetworkId(netId);
return result;
}
@@ -1234,7 +1283,8 @@
if (ipChanged || proxyChanged) {
currentConfig.linkProperties = linkProperties;
writeIpAndProxyConfigurations();
- sendConfiguredNetworksChangedBroadcast();
+ sendConfiguredNetworksChangedBroadcast(currentConfig,
+ WifiManager.CHANGE_REASON_CONFIG_CHANGE);
}
return new NetworkUpdateResult(ipChanged, proxyChanged);
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index d746810..8aa613b 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -294,12 +294,53 @@
/**
* Broadcast intent action indicating that the configured networks changed.
- * This can be as a result of adding/updating/deleting a network
+ * This can be as a result of adding/updating/deleting a network. If
+ * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set to true the new configuration
+ * can be retreived with the {@link #EXTRA_WIFI_CONFIGURATION} extra. If multiple
+ * Wi-Fi configurations changed, {@link #EXTRA_WIFI_CONFIGURATION} will not be present.
* @hide
*/
public static final String CONFIGURED_NETWORKS_CHANGED_ACTION =
"android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
/**
+ * The lookup key for a (@link android.net.wifi.WifiConfiguration} object representing
+ * the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION}
+ * broadcast is sent.
+ * @hide
+ */
+ public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
+ /**
+ * Multiple network configurations have changed.
+ * @see #CONFIGURED_NETWORKS_CHANGED_ACTION
+ *
+ * @hide
+ */
+ public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
+ /**
+ * The lookup key for an integer indicating the reason a Wi-Fi network configuration
+ * has changed. Only present if {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is {@code false}
+ * @see #CONFIGURED_NETWORKS_CHANGED_ACTION
+ * @hide
+ */
+ public static final String EXTRA_CHANGE_REASON = "changeReason";
+ /**
+ * The configuration is new and was added.
+ * @hide
+ */
+ public static final int CHANGE_REASON_ADDED = 0;
+ /**
+ * The configuration was removed and is no longer present in the system's list of
+ * configured networks.
+ * @hide
+ */
+ public static final int CHANGE_REASON_REMOVED = 1;
+ /**
+ * The configuration has changed as a result of explicit action or because the system
+ * took an automated action such as disabling a malfunctioning configuration.
+ * @hide
+ */
+ public static final int CHANGE_REASON_CONFIG_CHANGE = 2;
+ /**
* An access point scan has completed, and results are available from the supplicant.
* Call {@link #getScanResults()} to obtain the results.
*/
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 05a8ca7..cbf7bf8 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -394,7 +394,7 @@
* Starting and shutting down driver too quick causes problems leading to driver
* being in a bad state. Delay driver stop.
*/
- private static final int DELAYED_DRIVER_STOP_MS = 2 * 60 * 1000; /* 2 minutes */
+ private final int mDriverStopDelayMs;
private int mDelayedStopCounter;
private boolean mInDelayedStop = false;
@@ -563,6 +563,9 @@
mDefaultSupplicantScanIntervalMs = mContext.getResources().getInteger(
com.android.internal.R.integer.config_wifi_supplicant_scan_interval);
+ mDriverStopDelayMs = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_wifi_driver_stop_delay);
+
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
@@ -2589,7 +2592,7 @@
} else {
/* send regular delayed shut down */
sendMessageDelayed(obtainMessage(CMD_DELAYED_STOP_DRIVER,
- mDelayedStopCounter, 0), DELAYED_DRIVER_STOP_MS);
+ mDelayedStopCounter, 0), mDriverStopDelayMs);
}
break;
case CMD_START_DRIVER: