Merge "NativeDaemonConnector: fix doListCommand() to return *all* list elements"
diff --git a/api/current.xml b/api/current.xml
index 03e20fa4..cd200c1 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -20148,6 +20148,34 @@
visibility="public"
>
</method>
+<method name="getTagForPolicy"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="policyIdent" type="int">
+</parameter>
+</method>
+<method name="loadDescription"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pm" type="android.content.pm.PackageManager">
+</parameter>
+<exception name="Resources.NotFoundException" type="android.content.res.Resources.NotFoundException">
+</exception>
+</method>
<method name="loadIcon"
return="android.graphics.drawable.Drawable"
abstract="false"
@@ -20174,6 +20202,19 @@
<parameter name="pm" type="android.content.pm.PackageManager">
</parameter>
</method>
+<method name="usesPolicy"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="policyIdent" type="int">
+</parameter>
+</method>
<method name="writeToParcel"
return="void"
abstract="false"
@@ -20199,6 +20240,72 @@
visibility="public"
>
</field>
+<field name="USES_POLICY_FORCE_LOCK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="USES_POLICY_LIMIT_PASSWORD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="USES_POLICY_LIMIT_UNLOCK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="USES_POLICY_RESET_PASSWORD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="USES_POLICY_WATCH_LOGIN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="USES_POLICY_WIPE_DATA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<class name="DevicePolicyManager"
extends="java.lang.Object"
@@ -41567,6 +41674,16 @@
visibility="public"
>
</field>
+<field name="descriptionRes"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="enabled"
type="boolean"
transient="false"
@@ -131147,6 +131264,21 @@
<parameter name="name" type="java.lang.String">
</parameter>
</method>
+<method name="isLocationProviderEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cr" type="android.content.ContentResolver">
+</parameter>
+<parameter name="provider" type="java.lang.String">
+</parameter>
+</method>
<method name="putFloat"
return="boolean"
abstract="false"
@@ -131215,6 +131347,23 @@
<parameter name="value" type="java.lang.String">
</parameter>
</method>
+<method name="setLocationProviderEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cr" type="android.content.ContentResolver">
+</parameter>
+<parameter name="provider" type="java.lang.String">
+</parameter>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
<field name="ACCESSIBILITY_ENABLED"
type="java.lang.String"
transient="false"
@@ -132547,6 +132696,39 @@
visibility="public"
>
</field>
+<field name="SCREEN_BRIGHTNESS_MODE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""screen_brightness_mode""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCREEN_BRIGHTNESS_MODE_AUTOMATIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCREEN_BRIGHTNESS_MODE_MANUAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="SCREEN_OFF_TIMEOUT"
type="java.lang.String"
transient="false"
diff --git a/core/java/android/app/DeviceAdmin.java b/core/java/android/app/DeviceAdmin.java
index 16832db..9750d6e 100644
--- a/core/java/android/app/DeviceAdmin.java
+++ b/core/java/android/app/DeviceAdmin.java
@@ -82,6 +82,10 @@
* {@link DevicePolicyManager#getMinimumPasswordLength()
* DevicePolicyManager.getMinimumPasswordLength()}. You will generally
* handle this in {@link DeviceAdmin#onPasswordChanged(Context, Intent)}.
+ *
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to receive
+ * this broadcast.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PASSWORD_CHANGED
@@ -94,6 +98,10 @@
* {@link DevicePolicyManager#getCurrentFailedPasswordAttempts()
* DevicePolicyManager.getCurrentFailedPasswordAttempts()}. You will generally
* handle this in {@link DeviceAdmin#onPasswordFailed(Context, Intent)}.
+ *
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
+ * this broadcast.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PASSWORD_FAILED
@@ -102,6 +110,10 @@
/**
* Action sent to a device administrator when the user has successfully
* entered their password, after failing one or more times.
+ *
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
+ * this broadcast.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PASSWORD_SUCCEEDED
diff --git a/core/java/android/app/DeviceAdminInfo.java b/core/java/android/app/DeviceAdminInfo.java
index eac6e46..92fdbc8 100644
--- a/core/java/android/app/DeviceAdminInfo.java
+++ b/core/java/android/app/DeviceAdminInfo.java
@@ -19,21 +19,28 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.R;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
+import android.content.res.Resources.NotFoundException;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.Printer;
+import android.util.SparseArray;
import android.util.Xml;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
/**
* This class is used to specify meta information of a device administrator
@@ -43,11 +50,123 @@
static final String TAG = "DeviceAdminInfo";
/**
+ * A type of policy that this device admin can use: limit the passwords
+ * that the user can select, via {@link DevicePolicyManager#setPasswordMode}
+ * and {@link DevicePolicyManager#setMinimumPasswordLength}.
+ *
+ * <p>To control this policy, the device admin must have a "limit-password"
+ * tag in the "uses-policies" section of its meta-data.
+ */
+ public static final int USES_POLICY_LIMIT_PASSWORD = 0;
+
+ /**
+ * A type of policy that this device admin can use: able to watch login
+ * attempts from the user, via {@link DeviceAdmin#ACTION_PASSWORD_FAILED},
+ * {@link DeviceAdmin#ACTION_PASSWORD_SUCCEEDED}, and
+ * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts}.
+ *
+ * <p>To control this policy, the device admin must have a "watch-login"
+ * tag in the "uses-policies" section of its meta-data.
+ */
+ public static final int USES_POLICY_WATCH_LOGIN = 1;
+
+ /**
+ * A type of policy that this device admin can use: able to reset the
+ * user's password via
+ * {@link DevicePolicyManager#resetPassword}.
+ *
+ * <p>To control this policy, the device admin must have a "reset-password"
+ * tag in the "uses-policies" section of its meta-data.
+ */
+ public static final int USES_POLICY_RESET_PASSWORD = 2;
+
+ /**
+ * A type of policy that this device admin can use: able to limit the
+ * maximum lock timeout for the device via
+ * {@link DevicePolicyManager#setMaximumTimeToLock}.
+ *
+ * <p>To control this policy, the device admin must have a "limit-unlock"
+ * tag in the "uses-policies" section of its meta-data.
+ */
+ public static final int USES_POLICY_LIMIT_UNLOCK = 3;
+
+ /**
+ * A type of policy that this device admin can use: able to force the device
+ * to lock via{@link DevicePolicyManager#lockNow}.
+ *
+ * <p>To control this policy, the device admin must have a "force-lock"
+ * tag in the "uses-policies" section of its meta-data.
+ */
+ public static final int USES_POLICY_FORCE_LOCK = 4;
+
+ /**
+ * A type of policy that this device admin can use: able to factory
+ * reset the device, erasing all of the user's data, via
+ * {@link DevicePolicyManager#wipeData}.
+ *
+ * <p>To control this policy, the device admin must have a "wipe-data"
+ * tag in the "uses-policies" section of its meta-data.
+ */
+ public static final int USES_POLICY_WIPE_DATA = 5;
+
+ /** @hide */
+ public static class PolicyInfo {
+ final public String tag;
+ final public int label;
+ final public int description;
+
+ public PolicyInfo(String tagIn, int labelIn, int descriptionIn) {
+ tag = tagIn;
+ label = labelIn;
+ description = descriptionIn;
+ }
+ }
+
+ static HashMap<String, Integer> sKnownPolicies = new HashMap<String, Integer>();
+ static SparseArray<PolicyInfo> sRevKnownPolicies = new SparseArray<PolicyInfo>();
+
+ static {
+ sRevKnownPolicies.put(USES_POLICY_LIMIT_PASSWORD,
+ new PolicyInfo("limit-password",
+ com.android.internal.R.string.policylab_limitPassword,
+ com.android.internal.R.string.policydesc_limitPassword));
+ sRevKnownPolicies.put(USES_POLICY_WATCH_LOGIN,
+ new PolicyInfo("watch-login",
+ com.android.internal.R.string.policylab_watchLogin,
+ com.android.internal.R.string.policydesc_watchLogin));
+ sRevKnownPolicies.put(USES_POLICY_RESET_PASSWORD,
+ new PolicyInfo("reset-password",
+ com.android.internal.R.string.policylab_resetPassword,
+ com.android.internal.R.string.policydesc_resetPassword));
+ sRevKnownPolicies.put(USES_POLICY_LIMIT_UNLOCK,
+ new PolicyInfo("limit-unlock",
+ com.android.internal.R.string.policylab_limitUnlock,
+ com.android.internal.R.string.policydesc_limitUnlock));
+ sRevKnownPolicies.put(USES_POLICY_FORCE_LOCK,
+ new PolicyInfo("force-lock",
+ com.android.internal.R.string.policylab_forceLock,
+ com.android.internal.R.string.policydesc_forceLock));
+ sRevKnownPolicies.put(USES_POLICY_WIPE_DATA,
+ new PolicyInfo("wipe-data",
+ com.android.internal.R.string.policylab_wipeData,
+ com.android.internal.R.string.policydesc_wipeData));
+ for (int i=0; i<sRevKnownPolicies.size(); i++) {
+ sKnownPolicies.put(sRevKnownPolicies.valueAt(i).tag,
+ sRevKnownPolicies.keyAt(i));
+ }
+ }
+
+ /**
* The BroadcastReceiver that implements this device admin component.
*/
final ResolveInfo mReceiver;
/**
+ * The policies this administrator needs access to.
+ */
+ int mUsesPolicies;
+
+ /**
* Constructor.
*
* @param context The Context in which we are parsing the device admin.
@@ -86,6 +205,32 @@
com.android.internal.R.styleable.Wallpaper);
sa.recycle();
+
+ int outerDepth = parser.getDepth();
+ 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("uses-policies")) {
+ int innerDepth = parser.getDepth();
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ String policyName = parser.getName();
+ Integer val = sKnownPolicies.get(policyName);
+ if (val != null) {
+ mUsesPolicies |= 1 << val.intValue();
+ } else {
+ Log.w(TAG, "Unknown tag under uses-policies of "
+ + getComponent() + ": " + policyName);
+ }
+ }
+ }
+ }
} finally {
if (parser != null) parser.close();
}
@@ -93,6 +238,7 @@
DeviceAdminInfo(Parcel source) {
mReceiver = ResolveInfo.CREATOR.createFromParcel(source);
+ mUsesPolicies = source.readInt();
}
/**
@@ -137,6 +283,26 @@
}
/**
+ * Load user-visible description associated with this device admin.
+ *
+ * @param pm Supply a PackageManager used to load the device admin's
+ * resources.
+ */
+ public CharSequence loadDescription(PackageManager pm) throws NotFoundException {
+ if (mReceiver.activityInfo.descriptionRes != 0) {
+ String packageName = mReceiver.resolvePackageName;
+ ApplicationInfo applicationInfo = null;
+ if (packageName == null) {
+ packageName = mReceiver.activityInfo.packageName;
+ applicationInfo = mReceiver.activityInfo.applicationInfo;
+ }
+ return pm.getText(packageName,
+ mReceiver.activityInfo.descriptionRes, applicationInfo);
+ }
+ throw new NotFoundException();
+ }
+
+ /**
* Load the user-displayed icon for this device admin.
*
* @param pm Supply a PackageManager used to load the device admin's
@@ -146,6 +312,38 @@
return mReceiver.loadIcon(pm);
}
+ /**
+ * Return true if the device admin has requested that it be able to use
+ * the given policy control. The possible policy identifier inputs are:
+ * {@link #USES_POLICY_LIMIT_PASSWORD}, {@link #USES_POLICY_WATCH_LOGIN},
+ * {@link #USES_POLICY_RESET_PASSWORD}, {@link #USES_POLICY_LIMIT_UNLOCK},
+ * {@link #USES_POLICY_FORCE_LOCK}, {@link #USES_POLICY_WIPE_DATA}.
+ */
+ public boolean usesPolicy(int policyIdent) {
+ return (mUsesPolicies & (1<<policyIdent)) != 0;
+ }
+
+ /**
+ * Return the XML tag name for the given policy identifier. Valid identifiers
+ * are as per {@link #usesPolicy(int)}. If the given identifier is not
+ * known, null is returned.
+ */
+ public String getTagForPolicy(int policyIdent) {
+ return sRevKnownPolicies.get(policyIdent).tag;
+ }
+
+ /** @hide */
+ public ArrayList<PolicyInfo> getUsedPolicies() {
+ ArrayList<PolicyInfo> res = new ArrayList<PolicyInfo>();
+ for (int i=0; i<sRevKnownPolicies.size(); i++) {
+ int ident = sRevKnownPolicies.keyAt(i);
+ if (usesPolicy(ident)) {
+ res.add(sRevKnownPolicies.valueAt(i));
+ }
+ }
+ return res;
+ }
+
public void dump(Printer pw, String prefix) {
pw.println(prefix + "Receiver:");
mReceiver.dump(pw, prefix + " ");
@@ -164,6 +362,7 @@
*/
public void writeToParcel(Parcel dest, int flags) {
mReceiver.writeToParcel(dest, flags);
+ dest.writeInt(mUsesPolicies);
}
/**
diff --git a/core/java/android/app/DevicePolicyManager.java b/core/java/android/app/DevicePolicyManager.java
index 538ba5b..25e3230 100644
--- a/core/java/android/app/DevicePolicyManager.java
+++ b/core/java/android/app/DevicePolicyManager.java
@@ -163,6 +163,10 @@
* the user's preference, and any other considerations) is the one that
* is in effect.
*
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
* @param admin Which {@link DeviceAdmin} this request is associated with.
* @param mode The new desired mode. One of
* {@link #PASSWORD_MODE_UNSPECIFIED}, {@link #PASSWORD_MODE_SOMETHING},
@@ -205,6 +209,10 @@
* {@link #PASSWORD_MODE_NUMERIC} or {@link #PASSWORD_MODE_ALPHANUMERIC}
* with {@link #setPasswordMode}.
*
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
* @param admin Which {@link DeviceAdmin} this request is associated with.
* @param length The new desired minimum password length. A value of 0
* means there is no restriction.
@@ -239,6 +247,10 @@
* to meet the policy requirements (mode, minimum length) that have been
* requested.
*
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
* @return Returns true if the password meets the current requirements,
* else false.
*/
@@ -256,6 +268,10 @@
/**
* Retrieve the number of times the user has failed at entering a
* password since that last successful password entry.
+ *
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to be able to call
+ * this method; if it has not, a security exception will be thrown.
*/
public int getCurrentFailedPasswordAttempts() {
if (mService != null) {
@@ -277,6 +293,10 @@
* if it contains only digits, that is still an acceptable alphanumeric
* password.)
*
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
* @param password The new password for the user.
* @return Returns true if the password was applied, or false if it is
* not acceptable for the current constraints.
@@ -297,6 +317,10 @@
* maximum time for user activity until the device will lock. This limits
* the length that the user can set. It takes effect immediately.
*
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_LIMIT_UNLOCK} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
* @param admin Which {@link DeviceAdmin} this request is associated with.
* @param timeMs The new desired maximum time to lock in milliseconds.
* A value of 0 means there is no restriction.
@@ -329,6 +353,10 @@
/**
* Make the device lock immediately, as if the lock screen timeout has
* expired at the point of this call.
+ *
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} to be able to call
+ * this method; if it has not, a security exception will be thrown.
*/
public void lockNow() {
if (mService != null) {
@@ -345,6 +373,10 @@
* erasing all user data while next booting up. External storage such
* as SD cards will not be erased.
*
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
* @param flags Bit mask of additional options: currently must be 0.
*/
public void wipeData(int flags) {
diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java
index 1612ac9..5ca3fb54 100644
--- a/core/java/android/app/WallpaperInfo.java
+++ b/core/java/android/app/WallpaperInfo.java
@@ -21,6 +21,7 @@
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
@@ -204,7 +205,7 @@
return pm.getDrawable(mService.serviceInfo.packageName,
mThumbnailResource,
- null);
+ mService.serviceInfo.applicationInfo);
}
/**
@@ -212,25 +213,33 @@
*/
public CharSequence loadAuthor(PackageManager pm) throws NotFoundException {
if (mAuthorResource <= 0) throw new NotFoundException();
- return pm.getText(
- (mService.resolvePackageName != null)
- ? mService.resolvePackageName
- : getPackageName(),
- mAuthorResource,
- null);
+ String packageName = mService.resolvePackageName;
+ ApplicationInfo applicationInfo = null;
+ if (packageName == null) {
+ packageName = mService.serviceInfo.packageName;
+ applicationInfo = mService.serviceInfo.applicationInfo;
+ }
+ return pm.getText(packageName, mAuthorResource, applicationInfo);
}
/**
* Return a brief summary of this wallpaper's behavior.
*/
public CharSequence loadDescription(PackageManager pm) throws NotFoundException {
+ String packageName = mService.resolvePackageName;
+ ApplicationInfo applicationInfo = null;
+ if (packageName == null) {
+ packageName = mService.serviceInfo.packageName;
+ applicationInfo = mService.serviceInfo.applicationInfo;
+ }
+ if (mService.serviceInfo.descriptionRes != 0) {
+ return pm.getText(packageName, mService.serviceInfo.descriptionRes,
+ applicationInfo);
+
+ }
if (mDescriptionResource <= 0) throw new NotFoundException();
- return pm.getText(
- (mService.resolvePackageName != null)
- ? mService.resolvePackageName
- : getPackageName(),
- mDescriptionResource,
- null);
+ return pm.getText(packageName, mDescriptionResource,
+ mService.serviceInfo.applicationInfo);
}
/**
diff --git a/core/java/android/backup/BackupManager.java b/core/java/android/backup/BackupManager.java
index da1647a..0b27117 100644
--- a/core/java/android/backup/BackupManager.java
+++ b/core/java/android/backup/BackupManager.java
@@ -16,6 +16,7 @@
package android.backup;
+import android.backup.RestoreSession;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -115,19 +116,21 @@
*
* {@hide}
*/
- public IRestoreSession beginRestoreSession(String transport) {
+ public RestoreSession beginRestoreSession() {
if (!EVEN_THINK_ABOUT_DOING_RESTORE) {
return null;
}
- IRestoreSession binder = null;
+ RestoreSession session = null;
checkServiceBinder();
if (sService != null) {
try {
- binder = sService.beginRestoreSession(transport);
+ String transport = sService.getCurrentTransport();
+ IRestoreSession binder = sService.beginRestoreSession(transport);
+ session = new RestoreSession(mContext, binder);
} catch (RemoteException e) {
Log.d(TAG, "beginRestoreSession() couldn't connect");
}
}
- return binder;
+ return session;
}
}
diff --git a/core/java/android/backup/RestoreObserver.java b/core/java/android/backup/RestoreObserver.java
new file mode 100644
index 0000000..3be8c08
--- /dev/null
+++ b/core/java/android/backup/RestoreObserver.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.backup;
+
+/**
+ * Callback class for receiving progress reports during a restore operation. These
+ * methods will all be called on your application's main thread.
+ * @hide
+ */
+public abstract class RestoreObserver {
+ /**
+ * The restore operation has begun.
+ *
+ * @param numPackages The total number of packages being processed in
+ * this restore operation.
+ */
+ void restoreStarting(int numPackages) {
+ }
+
+ /**
+ * An indication of which package is being restored currently, out of the
+ * total number provided in the restoreStarting() callback. This method
+ * is not guaranteed to be called.
+ *
+ * @param nowBeingRestored The index, between 1 and the numPackages parameter
+ * to the restoreStarting() callback, of the package now being restored.
+ */
+ void onUpdate(int nowBeingRestored) {
+ }
+
+ /**
+ * The restore operation has completed.
+ *
+ * @param error Zero on success; a nonzero error code if the restore operation
+ * as a whole failed.
+ */
+ void restoreFinished(int error) {
+ }
+}
diff --git a/core/java/android/backup/RestoreSession.java b/core/java/android/backup/RestoreSession.java
new file mode 100644
index 0000000..119fc52
--- /dev/null
+++ b/core/java/android/backup/RestoreSession.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.backup;
+
+import android.backup.IRestoreSession;
+import android.backup.RestoreObserver;
+import android.backup.RestoreSet;
+import android.content.Context;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Interface for applications to use when managing a restore session.
+ * @hide
+ */
+public class RestoreSession {
+ static final String TAG = "RestoreSession";
+
+ final Context mContext;
+ IRestoreSession mBinder;
+ RestoreObserverWrapper mObserver = null;
+
+ /**
+ * Ask the current transport what the available restore sets are.
+ *
+ * @return A bundle containing two elements: an int array under the key
+ * "tokens" whose entries are a transport-private identifier for each backup set;
+ * and a String array under the key "names" whose entries are the user-meaningful
+ * text corresponding to the backup sets at each index in the tokens array.
+ * On error, returns null.
+ */
+ public RestoreSet[] getAvailableRestoreSets() {
+ try {
+ return mBinder.getAvailableRestoreSets();
+ } catch (RemoteException e) {
+ Log.d(TAG, "Can't contact server to get available sets");
+ return null;
+ }
+ }
+
+ /**
+ * Restore the given set onto the device, replacing the current data of any app
+ * contained in the restore set with the data previously backed up.
+ *
+ * @return Zero on success; nonzero on error. The observer will only receive
+ * progress callbacks if this method returned zero.
+ * @param token The token from {@link #getAvailableRestoreSets()} corresponding to
+ * the restore set that should be used.
+ * @param observer If non-null, this argument points to an object that will receive
+ * progress callbacks during the restore operation. These callbacks will occur
+ * on the main thread of the application.
+ */
+ public int performRestore(long token, RestoreObserver observer) {
+ int err = -1;
+ if (mObserver != null) {
+ Log.d(TAG, "performRestore() called during active restore");
+ return -1;
+ }
+ mObserver = new RestoreObserverWrapper(mContext, observer);
+ try {
+ err = mBinder.performRestore(token, mObserver);
+ } catch (RemoteException e) {
+ Log.d(TAG, "Can't contact server to perform restore");
+ }
+ return err;
+ }
+
+ /**
+ * End this restore session. After this method is called, the RestoreSession
+ * object is no longer valid.
+ *
+ * <p><b>Note:</b> The caller <i>must</i> invoke this method to end the restore session,
+ * even if {@link #getAvailableRestoreSets()} or
+ * {@link #performRestore(long, RestoreObserver)} failed.
+ */
+ public void endRestoreSession() {
+ try {
+ mBinder.endRestoreSession();
+ } catch (RemoteException e) {
+ Log.d(TAG, "Can't contact server to get available sets");
+ } finally {
+ mBinder = null;
+ }
+ }
+
+ /*
+ * Nonpublic implementation here
+ */
+
+ RestoreSession(Context context, IRestoreSession binder) {
+ mContext = context;
+ mBinder = binder;
+ }
+
+ /*
+ * We wrap incoming binder calls with a private class implementation that
+ * redirects them into main-thread actions. This accomplishes two things:
+ * first, it ensures that the app's code is run on their own main thread,
+ * never with system Binder identity; and second, it serializes the restore
+ * progress callbacks nicely within the usual main-thread lifecycle pattern.
+ */
+ private class RestoreObserverWrapper extends IRestoreObserver.Stub {
+ final Handler mHandler;
+ final RestoreObserver mAppObserver;
+
+ RestoreObserverWrapper(Context context, RestoreObserver appObserver) {
+ mHandler = new Handler(context.getMainLooper());
+ mAppObserver = appObserver;
+ }
+
+ // Wrap the IRestoreObserver -> RestoreObserver callthrough in Runnables
+ // posted to the app's main thread looper.
+ class RestoreStartingRunnable implements Runnable {
+ int mNumPackages;
+
+ RestoreStartingRunnable(int numPackages) {
+ mNumPackages = numPackages;
+ }
+
+ public void run() {
+ mAppObserver.restoreStarting(mNumPackages);
+ }
+ }
+
+ class OnUpdateRunnable implements Runnable {
+ int mNowRestoring;
+
+ OnUpdateRunnable(int nowRestoring) {
+ mNowRestoring = nowRestoring;
+ }
+
+ public void run() {
+ mAppObserver.onUpdate(mNowRestoring);
+ }
+ }
+
+ class RestoreFinishedRunnable implements Runnable {
+ int mError;
+
+ RestoreFinishedRunnable(int error) {
+ mError = error;
+ }
+
+ public void run() {
+ mAppObserver.restoreFinished(mError);
+ }
+ }
+
+ // The actual redirection code is quite simple using just the
+ // above Runnable subclasses
+ public void restoreStarting(int numPackages) {
+ mHandler.post(new RestoreStartingRunnable(numPackages));
+ }
+
+ public void onUpdate(int nowBeingRestored) {
+ mHandler.post(new OnUpdateRunnable(nowBeingRestored));
+ }
+
+ public void restoreFinished(int error) {
+ mHandler.post(new RestoreFinishedRunnable(error));
+ }
+ }
+}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index a7ea507..808c839b 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -234,6 +234,14 @@
public static final int FLAG_ON_SDCARD = 1<<19;
/**
+ * Value for {@link #flags}: Set to true if the application is
+ * native-debuggable, i.e. embeds a gdbserver binary in its .apk
+ *
+ * {@hide}
+ */
+ public static final int FLAG_NATIVE_DEBUGGABLE = 1<<20;
+
+ /**
* Flags associated with the application. Any combination of
* {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
* {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index 73c9244..338c62b6 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2008 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 android.content.pm;
import android.graphics.drawable.Drawable;
@@ -27,6 +43,13 @@
public String processName;
/**
+ * A string resource identifier (in the package's resources) containing
+ * a user-readable description of the component. From the "description"
+ * attribute or, if not set, 0.
+ */
+ public int descriptionRes;
+
+ /**
* Indicates whether or not this component may be instantiated. Note that this value can be
* overriden by the one in its parent {@link ApplicationInfo}.
*/
@@ -47,6 +70,7 @@
super(orig);
applicationInfo = orig.applicationInfo;
processName = orig.processName;
+ descriptionRes = orig.descriptionRes;
enabled = orig.enabled;
exported = orig.exported;
}
@@ -108,6 +132,9 @@
super.dumpFront(pw, prefix);
pw.println(prefix + "enabled=" + enabled + " exported=" + exported
+ " processName=" + processName);
+ if (descriptionRes != 0) {
+ pw.println(prefix + "description=" + descriptionRes);
+ }
}
protected void dumpBack(Printer pw, String prefix) {
@@ -124,6 +151,7 @@
super.writeToParcel(dest, parcelableFlags);
applicationInfo.writeToParcel(dest, parcelableFlags);
dest.writeString(processName);
+ dest.writeInt(descriptionRes);
dest.writeInt(enabled ? 1 : 0);
dest.writeInt(exported ? 1 : 0);
}
@@ -132,6 +160,7 @@
super(source);
applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source);
processName = source.readString();
+ descriptionRes = source.readInt();
enabled = (source.readInt() != 0);
exported = (source.readInt() != 0);
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 8a5df32..bbde0a6 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -119,15 +119,18 @@
static class ParseComponentArgs extends ParsePackageItemArgs {
final String[] sepProcesses;
final int processRes;
+ final int descriptionRes;
final int enabledRes;
int flags;
ParseComponentArgs(Package _owner, String[] _outError,
int _nameRes, int _labelRes, int _iconRes,
- String[] _sepProcesses, int _processRes,int _enabledRes) {
+ String[] _sepProcesses, int _processRes,
+ int _descriptionRes, int _enabledRes) {
super(_owner, _outError, _nameRes, _labelRes, _iconRes);
sepProcesses = _sepProcesses;
processRes = _processRes;
+ descriptionRes = _descriptionRes;
enabledRes = _enabledRes;
}
}
@@ -1602,6 +1605,7 @@
com.android.internal.R.styleable.AndroidManifestActivity_icon,
mSeparateProcesses,
com.android.internal.R.styleable.AndroidManifestActivity_process,
+ com.android.internal.R.styleable.AndroidManifestActivity_description,
com.android.internal.R.styleable.AndroidManifestActivity_enabled);
}
@@ -1803,6 +1807,7 @@
com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
mSeparateProcesses,
0,
+ com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
mParseActivityAliasArgs.tag = "<activity-alias>";
}
@@ -1837,6 +1842,9 @@
info.nonLocalizedLabel = target.info.nonLocalizedLabel;
info.launchMode = target.info.launchMode;
info.processName = target.info.processName;
+ if (info.descriptionRes == 0) {
+ info.descriptionRes = target.info.descriptionRes;
+ }
info.screenOrientation = target.info.screenOrientation;
info.taskAffinity = target.info.taskAffinity;
info.theme = target.info.theme;
@@ -1926,6 +1934,7 @@
com.android.internal.R.styleable.AndroidManifestProvider_icon,
mSeparateProcesses,
com.android.internal.R.styleable.AndroidManifestProvider_process,
+ com.android.internal.R.styleable.AndroidManifestProvider_description,
com.android.internal.R.styleable.AndroidManifestProvider_enabled);
mParseProviderArgs.tag = "<provider>";
}
@@ -2188,6 +2197,7 @@
com.android.internal.R.styleable.AndroidManifestService_icon,
mSeparateProcesses,
com.android.internal.R.styleable.AndroidManifestService_process,
+ com.android.internal.R.styleable.AndroidManifestService_description,
com.android.internal.R.styleable.AndroidManifestService_enabled);
mParseServiceArgs.tag = "<service>";
}
@@ -2640,6 +2650,11 @@
owner.applicationInfo.processName, args.sa.getNonResourceString(args.processRes),
args.flags, args.sepProcesses, args.outError);
}
+
+ if (args.descriptionRes != 0) {
+ outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
+ }
+
outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8172ac4..ecfea00 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1130,19 +1130,16 @@
/**
* Control whether to enable automatic brightness mode.
- * @hide
*/
public static final String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
/**
* SCREEN_BRIGHTNESS_MODE value for manual mode.
- * @hide
*/
public static final int SCREEN_BRIGHTNESS_MODE_MANUAL = 0;
/**
* SCREEN_BRIGHTNESS_MODE value for manual mode.
- * @hide
*/
public static final int SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1;
@@ -2977,8 +2974,6 @@
* @param cr the content resolver to use
* @param provider the location provider to query
* @return true if the provider is enabled
- *
- * @hide
*/
public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED);
@@ -2996,8 +2991,6 @@
* @param cr the content resolver to use
* @param provider the location provider to enable or disable
* @param enabled true if the provider should be enabled
- *
- * @hide
*/
public static final void setLocationProviderEnabled(ContentResolver cr,
String provider, boolean enabled) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 56650a6..93e72ff 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4607,14 +4607,11 @@
break;
}
} else {
- if (mPreventDrag == PREVENT_DRAG_MAYBE_YES) {
- // if mPreventDrag is not confirmed, treat it as
- // no so that it won't block tap or double tap.
- mPreventDrag = PREVENT_DRAG_NO;
- mPreventLongPress = false;
- mPreventDoubleTap = false;
- }
- if (mPreventDrag == PREVENT_DRAG_NO) {
+ // mPreventDrag can be PREVENT_DRAG_MAYBE_YES in
+ // TOUCH_INIT_MODE. To give WebCoreThread a little
+ // more time to send PREVENT_TOUCH_ID, we check
+ // again in responding RELEASE_SINGLE_TAP.
+ if (mPreventDrag != PREVENT_DRAG_YES) {
if (mTouchMode == TOUCH_INIT_MODE) {
mPrivateHandler.sendMessageDelayed(
mPrivateHandler.obtainMessage(
@@ -5631,6 +5628,13 @@
break;
}
case RELEASE_SINGLE_TAP: {
+ if (mPreventDrag == PREVENT_DRAG_MAYBE_YES) {
+ // if mPreventDrag is not confirmed, treat it as
+ // no so that it won't block tap.
+ mPreventDrag = PREVENT_DRAG_NO;
+ mPreventLongPress = false;
+ mPreventDoubleTap = false;
+ }
if (mPreventDrag == PREVENT_DRAG_NO) {
mTouchMode = TOUCH_DONE_MODE;
doShortPress();
@@ -5863,7 +5867,7 @@
// updates is a C++ pointer to a Vector of
// AnimationValues that we apply to the layers.
// The Vector is deallocated in nativeUpdateLayers().
- nativeUpdateLayers(mRootLayer, updates);
+ nativeUpdateLayers(updates);
}
invalidate();
break;
@@ -5985,10 +5989,22 @@
}
mFullScreenHolder = new PluginFullScreenHolder(
WebView.this, data.mNpp);
+ // as we are sharing the View between full screen and
+ // embedded mode, we have to remove the
+ // AbsoluteLayout.LayoutParams set by embedded mode to
+ // ViewGroup.LayoutParams before adding it to the dialog
+ data.mView.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT,
+ ViewGroup.LayoutParams.FILL_PARENT));
mFullScreenHolder.setContentView(data.mView);
mFullScreenHolder.setCancelable(false);
mFullScreenHolder.setCanceledOnTouchOutside(false);
mFullScreenHolder.show();
+ } else if (mFullScreenHolder == null) {
+ // this may happen if user dismisses the fullscreen and
+ // then the WebCore re-position message finally reached
+ // the UI thread.
+ break;
}
// move the matching embedded view fully into the view so
// that touch will be valid instead of rejected due to out
@@ -6602,7 +6618,7 @@
private native void nativeDestroyLayer(int layer);
private native int nativeEvaluateLayersAnimations(int layer);
private native boolean nativeLayersHaveAnimations(int layer);
- private native void nativeUpdateLayers(int layer, int updates);
+ private native void nativeUpdateLayers(int updates);
private native void nativeDrawLayers(int layer,
int scrollX, int scrollY,
int width, int height,
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index a09f23c..aa14c81 100755
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -146,6 +146,19 @@
}
}
+ /**
+ * Utility to retrieve a view displaying a single permission.
+ */
+ public static View getPermissionItemView(Context context,
+ CharSequence grpName, CharSequence description, boolean dangerous) {
+ LayoutInflater inflater = (LayoutInflater)context.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ Drawable icon = context.getResources().getDrawable(dangerous
+ ? R.drawable.ic_bullet_key_permission : R.drawable.ic_text_dot);
+ return getPermissionItemView(context, inflater, grpName,
+ description, dangerous, icon);
+ }
+
private void getAllUsedPermissions(int sharedUid, Set<PermissionInfo> permSet) {
String sharedPkgList[] = mPm.getPackagesForUid(sharedUid);
if(sharedPkgList == null || (sharedPkgList.length == 0)) {
@@ -304,15 +317,20 @@
mNoPermsView.setVisibility(View.VISIBLE);
}
- private View getPermissionItemView(CharSequence grpName, String permList,
+ private View getPermissionItemView(CharSequence grpName, CharSequence permList,
boolean dangerous) {
- View permView = mInflater.inflate(R.layout.app_permission_item, null);
- Drawable icon = dangerous ? mDangerousIcon : mNormalIcon;
+ return getPermissionItemView(mContext, mInflater, grpName, permList,
+ dangerous, dangerous ? mDangerousIcon : mNormalIcon);
+ }
+
+ private static View getPermissionItemView(Context context, LayoutInflater inflater,
+ CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
+ View permView = inflater.inflate(R.layout.app_permission_item, null);
TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
if (dangerous) {
- final Resources resources = mContext.getResources();
+ final Resources resources = context.getResources();
permGrpView.setTextColor(resources.getColor(R.color.perms_dangerous_grp_color));
permDescView.setTextColor(resources.getColor(R.color.perms_dangerous_perm_color));
}
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 65f6845..9965fe5 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -645,6 +645,23 @@
return chunkObject;
}
+static void nativeSetDefaultConfig(JNIEnv* env, jobject, int nativeConfig) {
+ SkBitmap::Config config = static_cast<SkBitmap::Config>(nativeConfig);
+
+ // these are the only default configs that make sense for codecs right now
+ static const SkBitmap::Config gValidDefConfig[] = {
+ SkBitmap::kRGB_565_Config,
+ SkBitmap::kARGB_8888_Config,
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gValidDefConfig); i++) {
+ if (config == gValidDefConfig[i]) {
+ SkImageDecoder::SetDeviceConfig(config);
+ break;
+ }
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
static JNINativeMethod gMethods[] = {
@@ -671,8 +688,9 @@
{ "nativeScaleNinePatch",
"([BFLandroid/graphics/Rect;)[B",
(void*)nativeScaleNinePatch
- }
+ },
+ { "nativeSetDefaultConfig", "(I)V", (void*)nativeSetDefaultConfig },
};
static JNINativeMethod gOptionsMethods[] = {
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index c6ef3a0..7728c50 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -938,6 +938,7 @@
is a period then it is appended to your package name. -->
<attr name="name" />
<attr name="label" />
+ <attr name="description" />
<attr name="icon" />
<attr name="process" />
<attr name="authorities" />
@@ -1016,6 +1017,7 @@
is a period then it is appended to your package name. -->
<attr name="name" />
<attr name="label" />
+ <attr name="description" />
<attr name="icon" />
<attr name="permission" />
<attr name="process" />
@@ -1047,6 +1049,7 @@
is a period then it is appended to your package name. -->
<attr name="name" />
<attr name="label" />
+ <attr name="description" />
<attr name="icon" />
<attr name="permission" />
<attr name="process" />
@@ -1078,6 +1081,7 @@
<attr name="name" />
<attr name="theme" />
<attr name="label" />
+ <attr name="description" />
<attr name="icon" />
<attr name="launchMode" />
<attr name="screenOrientation" />
@@ -1130,6 +1134,7 @@
"com.mycompany.MyName". -->
<attr name="targetActivity" format="string" />
<attr name="label" />
+ <attr name="description" />
<attr name="icon" />
<attr name="permission" />
<!-- Specify whether the activity-alias is enabled or not (that is, can be instantiated by the system).
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 265dacd..0ef07ff 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1157,6 +1157,40 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_cache_filesystem">Allows an application to read and write the cache filesystem.</string>
+ <!-- Policy administration -->
+
+ <!-- Title of policy access to limiting the user's password choices -->
+ <string name="policylab_limitPassword">Limit password</string>
+ <!-- Description of policy access to limiting the user's password choices -->
+ <string name="policydesc_limitPassword">Restrict the types of passwords you
+ are allowed to use.</string>
+ <!-- Title of policy access to watch user login attempts -->
+ <string name="policylab_watchLogin">Watch login attempts</string>
+ <!-- Description of policy access to watch user login attempts -->
+ <string name="policydesc_watchLogin">Monitor attempts to login to
+ the device, in particular to respond to failed login attempts.</string>
+ <!-- Title of policy access to reset user's password -->
+ <string name="policylab_resetPassword">Reset your password</string>
+ <!-- Description of policy access to reset user's password -->
+ <string name="policydesc_resetPassword">Force your password
+ to a new value, requiring the administrator give it to you
+ before you can log in.</string>
+ <!-- Title of policy access to limiting the user's unlock timeout -->
+ <string name="policylab_limitUnlock">Limit lock timeout</string>
+ <!-- Description of policy access to limiting the user's unlock timeout -->
+ <string name="policydesc_limitUnlock">Restrict the unlock timeout
+ durations you can select.</string>
+ <!-- Title of policy access to force lock the device -->
+ <string name="policylab_forceLock">Force lock</string>
+ <!-- Description of policy access to limiting the user's password choices -->
+ <string name="policydesc_forceLock">Force the device to immediately lock,
+ requiring that its password is re-entered.</string>
+ <!-- Title of policy access to wipe the user's data -->
+ <string name="policylab_wipeData">Erase all data</string>
+ <!-- Description of policy access to wipe the user's data -->
+ <string name="policydesc_wipeData">Perform a factory reset, deleting
+ all of your data without any confirmation from you.</string>
+
<!-- The order of these is important, don't reorder without changing Contacts.java --> <skip />
<!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. -->
<string-array name="phoneTypes">
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 3c03eed..2313f4c 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -558,6 +558,30 @@
return decodeFileDescriptor(fd, null, null);
}
+ /**
+ * Set the default config used for decoding bitmaps. This config is
+ * presented to the codec if the caller did not specify a preferred config
+ * in their call to decode...
+ *
+ * The default value is chosen by the system to best match the device's
+ * screen and memory constraints.
+ *
+ * @param config The preferred config for decoding bitmaps. If null, then
+ * a suitable default is chosen by the system.
+ *
+ * @hide - only called by the browser at the moment, but should be stable
+ * enough to expose if needed
+ */
+ public static void setDefaultConfig(Bitmap.Config config) {
+ if (config == null) {
+ // pick this for now, as historically it was our default.
+ // However, if we have a smarter algorithm, we can change this.
+ config = Bitmap.Config.RGB_565;
+ }
+ nativeSetDefaultConfig(config.nativeInt);
+ }
+
+ private static native void nativeSetDefaultConfig(int nativeConfig);
private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
Rect padding, Options opts);
private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h
index 6ee9869..372909a 100644
--- a/include/media/stagefright/AMRWriter.h
+++ b/include/media/stagefright/AMRWriter.h
@@ -20,23 +20,23 @@
#include <stdio.h>
-#include <utils/RefBase.h>
+#include <media/stagefright/MediaWriter.h>
#include <utils/threads.h>
namespace android {
struct MediaSource;
-struct AMRWriter : public RefBase {
+struct AMRWriter : public MediaWriter {
AMRWriter(const char *filename);
AMRWriter(int fd);
status_t initCheck() const;
- status_t addSource(const sp<MediaSource> &source);
-
- status_t start();
- void stop();
+ virtual status_t addSource(const sp<MediaSource> &source);
+ virtual bool reachedEOS();
+ virtual status_t start();
+ virtual void stop();
protected:
virtual ~AMRWriter();
@@ -49,6 +49,7 @@
sp<MediaSource> mSource;
bool mStarted;
volatile bool mDone;
+ bool mReachedEOS;
pthread_t mThread;
static void *ThreadWrapper(void *);
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 2ca04fa..6b93f19 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -20,8 +20,8 @@
#include <stdio.h>
+#include <media/stagefright/MediaWriter.h>
#include <utils/List.h>
-#include <utils/RefBase.h>
#include <utils/threads.h>
namespace android {
@@ -30,15 +30,15 @@
class MediaSource;
class MetaData;
-class MPEG4Writer : public RefBase {
+class MPEG4Writer : public MediaWriter {
public:
MPEG4Writer(const char *filename);
MPEG4Writer(int fd);
- void addSource(const sp<MediaSource> &source);
- status_t start();
- bool reachedEOS();
- void stop();
+ virtual status_t addSource(const sp<MediaSource> &source);
+ virtual status_t start();
+ virtual bool reachedEOS();
+ virtual void stop();
void beginBox(const char *fourcc);
void writeInt8(int8_t x);
diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h
new file mode 100644
index 0000000..b8232c6
--- /dev/null
+++ b/include/media/stagefright/MediaWriter.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_WRITER_H_
+
+#define MEDIA_WRITER_H_
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct MediaSource;
+
+struct MediaWriter : public RefBase {
+ MediaWriter() {}
+
+ virtual status_t addSource(const sp<MediaSource> &source) = 0;
+ virtual bool reachedEOS() = 0;
+ virtual status_t start() = 0;
+ virtual void stop() = 0;
+
+protected:
+ virtual ~MediaWriter() {}
+
+private:
+ MediaWriter(const MediaWriter &);
+ MediaWriter &operator=(const MediaWriter &);
+};
+
+} // namespace android
+
+#endif // MEDIA_WRITER_H_
diff --git a/libs/rs/rsUtils.h b/libs/rs/rsUtils.h
index 3c6da68..07f8933 100644
--- a/libs/rs/rsUtils.h
+++ b/libs/rs/rsUtils.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_RS_UTILS_H
#define ANDROID_RS_UTILS_H
+#define LOG_NDEBUG 0
#define LOG_TAG "RenderScript"
#include <utils/Log.h>
#include <utils/Vector.h>
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index 4aac455..c4d4f99 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -489,7 +489,6 @@
{
int version;
int fd;
- int attempt;
struct pollfd *new_mFDs;
device_t **new_devices;
char **new_device_names;
@@ -502,16 +501,11 @@
AutoMutex _l(mLock);
- for (attempt = 0; attempt < 10; attempt++) {
- fd = open(deviceName, O_RDWR);
- if (fd >= 0) break;
- usleep(100);
- }
+ fd = open(deviceName, O_RDWR);
if(fd < 0) {
LOGE("could not open %s, %s\n", deviceName, strerror(errno));
return -1;
}
- LOGV("Opened device: %s (%d failures)", deviceName, attempt);
if(ioctl(fd, EVIOCGVERSION, &version)) {
LOGE("could not get driver version for %s, %s\n", deviceName, strerror(errno));
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index a55273d..6383f0c 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -20,6 +20,8 @@
#include "StagefrightRecorder.h"
+#include <media/stagefright/AudioSource.h>
+#include <media/stagefright/AMRWriter.h>
#include <media/stagefright/CameraSource.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/MediaDebug.h>
@@ -146,7 +148,90 @@
return UNKNOWN_ERROR;
}
- if (mVideoSource == VIDEO_SOURCE_CAMERA) {
+ switch (mOutputFormat) {
+ case OUTPUT_FORMAT_DEFAULT:
+ case OUTPUT_FORMAT_THREE_GPP:
+ case OUTPUT_FORMAT_MPEG_4:
+ return startMPEG4Recording();
+
+ case OUTPUT_FORMAT_AMR_NB:
+ case OUTPUT_FORMAT_AMR_WB:
+ return startAMRRecording();
+
+ default:
+ return UNKNOWN_ERROR;
+ }
+}
+
+sp<MediaSource> StagefrightRecorder::createAMRAudioSource() {
+ uint32_t sampleRate =
+ mAudioEncoder == AUDIO_ENCODER_AMR_NB ? 8000 : 16000;
+
+ sp<AudioSource> audioSource =
+ new AudioSource(
+ mAudioSource,
+ sampleRate,
+ AudioSystem::CHANNEL_IN_MONO);
+
+ status_t err = audioSource->initCheck();
+
+ if (err != OK) {
+ return NULL;
+ }
+
+ sp<MetaData> encMeta = new MetaData;
+ encMeta->setCString(
+ kKeyMIMEType,
+ mAudioEncoder == AUDIO_ENCODER_AMR_NB
+ ? MEDIA_MIMETYPE_AUDIO_AMR_NB : MEDIA_MIMETYPE_AUDIO_AMR_WB);
+
+ encMeta->setInt32(kKeyChannelCount, 1);
+ encMeta->setInt32(kKeySampleRate, sampleRate);
+
+ OMXClient client;
+ CHECK_EQ(client.connect(), OK);
+
+ sp<MediaSource> audioEncoder =
+ OMXCodec::Create(client.interface(), encMeta,
+ true /* createEncoder */, audioSource);
+
+ return audioEncoder;
+}
+
+status_t StagefrightRecorder::startAMRRecording() {
+ if (mAudioSource == AUDIO_SOURCE_LIST_END
+ || mVideoSource != VIDEO_SOURCE_LIST_END) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (mOutputFormat == OUTPUT_FORMAT_AMR_NB
+ && mAudioEncoder != AUDIO_ENCODER_DEFAULT
+ && mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
+ return UNKNOWN_ERROR;
+ } else if (mOutputFormat == OUTPUT_FORMAT_AMR_WB
+ && mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
+ return UNKNOWN_ERROR;
+ }
+
+ sp<MediaSource> audioEncoder = createAMRAudioSource();
+
+ if (audioEncoder == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ CHECK(mOutputFd >= 0);
+ mWriter = new AMRWriter(dup(mOutputFd));
+ mWriter->addSource(audioEncoder);
+ mWriter->start();
+
+ return OK;
+}
+
+status_t StagefrightRecorder::startMPEG4Recording() {
+ mWriter = new MPEG4Writer(dup(mOutputFd));
+
+ if (mVideoSource == VIDEO_SOURCE_DEFAULT
+ || mVideoSource == VIDEO_SOURCE_CAMERA) {
CHECK(mCamera != NULL);
sp<CameraSource> cameraSource =
@@ -193,11 +278,20 @@
true /* createEncoder */, cameraSource);
CHECK(mOutputFd >= 0);
- mWriter = new MPEG4Writer(dup(mOutputFd));
mWriter->addSource(encoder);
- mWriter->start();
}
+ if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+ sp<MediaSource> audioEncoder = createAMRAudioSource();
+
+ if (audioEncoder == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ mWriter->addSource(audioEncoder);
+ }
+
+ mWriter->start();
return OK;
}
@@ -235,7 +329,9 @@
}
status_t StagefrightRecorder::getMaxAmplitude(int *max) {
- return UNKNOWN_ERROR;
+ *max = 0;
+
+ return OK;
}
} // namespace android
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 56c4e0e..7ec412d 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -23,7 +23,8 @@
namespace android {
-class MPEG4Writer;
+struct MediaSource;
+struct MediaWriter;
struct StagefrightRecorder : public MediaRecorderBase {
StagefrightRecorder();
@@ -54,7 +55,7 @@
sp<ICamera> mCamera;
sp<ISurface> mPreviewSurface;
sp<IMediaPlayerClient> mListener;
- sp<MPEG4Writer> mWriter;
+ sp<MediaWriter> mWriter;
audio_source mAudioSource;
video_source mVideoSource;
@@ -66,6 +67,10 @@
String8 mParams;
int mOutputFd;
+ status_t startMPEG4Recording();
+ status_t startAMRRecording();
+ sp<MediaSource> createAMRAudioSource();
+
StagefrightRecorder(const StagefrightRecorder &);
StagefrightRecorder &operator=(const StagefrightRecorder &);
};
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index 7b681f12..caff452 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -115,6 +115,7 @@
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ mReachedEOS = false;
mDone = false;
pthread_create(&mThread, &attr, ThreadWrapper, this);
@@ -179,6 +180,14 @@
break;
}
}
+
+ Mutex::Autolock autoLock(mLock);
+ mReachedEOS = true;
+}
+
+bool AMRWriter::reachedEOS() {
+ Mutex::Autolock autoLock(mLock);
+ return mReachedEOS;
}
} // namespace android
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 367459f..aee4d15 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -92,9 +92,11 @@
mTracks.clear();
}
-void MPEG4Writer::addSource(const sp<MediaSource> &source) {
+status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
Track *track = new Track(this, source);
mTracks.push_back(track);
+
+ return OK;
}
status_t MPEG4Writer::start() {
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 2e45512..72e26f8 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -161,7 +161,7 @@
= new HashMap<String,IBackupTransport>();
String mCurrentTransport;
IBackupTransport mLocalTransport, mGoogleTransport;
- RestoreSession mActiveRestoreSession;
+ ActiveRestoreSession mActiveRestoreSession;
class RestoreParams {
public IBackupTransport transport;
@@ -2068,20 +2068,20 @@
Log.d(TAG, "Restore session requested but one already active");
return null;
}
- mActiveRestoreSession = new RestoreSession(transport);
+ mActiveRestoreSession = new ActiveRestoreSession(transport);
}
return mActiveRestoreSession;
}
// ----- Restore session -----
- class RestoreSession extends IRestoreSession.Stub {
+ class ActiveRestoreSession extends IRestoreSession.Stub {
private static final String TAG = "RestoreSession";
private IBackupTransport mRestoreTransport = null;
RestoreSet[] mRestoreSets = null;
- RestoreSession(String transport) {
+ ActiveRestoreSession(String transport) {
mRestoreTransport = getTransport(transport);
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 5a8d35f..4417d7b 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -828,6 +828,28 @@
info.getExtraInfo());
}
+ NetworkStateTracker newNet = tryFailover(prevNetType);
+ if (newNet != null) {
+ NetworkInfo switchTo = newNet.getNetworkInfo();
+ intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
+ } else {
+ intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
+ }
+ // do this before we broadcast the change
+ handleConnectivityChange();
+
+ sendStickyBroadcast(intent);
+ /*
+ * If the failover network is already connected, then immediately send
+ * out a followup broadcast indicating successful failover
+ */
+ if (newNet != null && newNet.getNetworkInfo().isConnected()) {
+ sendConnectedBroadcast(newNet.getNetworkInfo());
+ }
+ }
+
+ // returns -1 if no failover available
+ private NetworkStateTracker tryFailover(int prevNetType) {
/*
* If this is a default network, check if other defaults are available
* or active
@@ -840,8 +862,7 @@
int newType = -1;
int newPriority = -1;
- for (int checkType=0; checkType <=
- ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
+ for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
if (checkType == prevNetType) continue;
if (mNetAttributes[checkType] == null) continue;
if (mNetAttributes[checkType].isDefault()) {
@@ -884,29 +905,13 @@
switchTo.getTypeName());
}
}
- intent.putExtra(ConnectivityManager.
- EXTRA_OTHER_NETWORK_INFO, switchTo);
} else {
- intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
- true);
newNet.reconnect();
}
- } else {
- intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
- true);
}
}
- // do this before we broadcast the change
- handleConnectivityChange();
-
- sendStickyBroadcast(intent);
- /*
- * If the failover network is already connected, then immediately send
- * out a followup broadcast indicating successful failover
- */
- if (newNet != null && newNet.getNetworkInfo().isConnected())
- sendConnectedBroadcast(newNet.getNetworkInfo());
+ return newNet;
}
private void sendConnectedBroadcast(NetworkInfo info) {
@@ -964,7 +969,25 @@
intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
info.setFailover(false);
}
+
+ NetworkStateTracker newNet = tryFailover(info.getType());
+ if (newNet != null) {
+ NetworkInfo switchTo = newNet.getNetworkInfo();
+ intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
+ } else {
+ intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
+ }
+ // do this before we broadcast the change
+ handleConnectivityChange();
+
sendStickyBroadcast(intent);
+ /*
+ * If the failover network is already connected, then immediately send
+ * out a followup broadcast indicating successful failover
+ */
+ if (newNet != null && newNet.getNetworkInfo().isConnected()) {
+ sendConnectedBroadcast(newNet.getNetworkInfo());
+ }
}
private void sendStickyBroadcast(Intent intent) {
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 36da4eb..fbd5317 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -91,7 +91,8 @@
return mIPowerManager;
}
- ActiveAdmin getActiveAdminForCallerLocked(ComponentName who) throws SecurityException {
+ ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
+ throws SecurityException {
if (mActiveAdmin != null && mActiveAdmin.getUid() == Binder.getCallingUid()) {
if (who != null) {
if (!who.getPackageName().equals(mActiveAdmin.info.getActivityInfo().packageName)
@@ -99,20 +100,27 @@
throw new SecurityException("Current admin is not " + who);
}
}
+ if (!mActiveAdmin.info.usesPolicy(reqPolicy)) {
+ throw new SecurityException("Admin " + mActiveAdmin.info.getComponent()
+ + " did not specify uses-policy for: "
+ + mActiveAdmin.info.getTagForPolicy(reqPolicy));
+ }
return mActiveAdmin;
}
throw new SecurityException("Current admin is not owned by uid " + Binder.getCallingUid());
}
-
- void sendAdminCommandLocked(ActiveAdmin policy, String action) {
+ void sendAdminCommandLocked(ActiveAdmin admin, String action) {
Intent intent = new Intent(action);
- intent.setComponent(policy.info.getComponent());
+ intent.setComponent(admin.info.getComponent());
mContext.sendBroadcast(intent);
}
- void sendAdminCommandLocked(String action) {
+ void sendAdminCommandLocked(String action, int reqPolicy) {
if (mActiveAdmin != null) {
+ if (mActiveAdmin.info.usesPolicy(reqPolicy)) {
+ return;
+ }
sendAdminCommandLocked(mActiveAdmin, action);
}
}
@@ -353,7 +361,8 @@
if (who == null) {
throw new NullPointerException("ComponentName is null");
}
- ActiveAdmin ap = getActiveAdminForCallerLocked(who);
+ ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.passwordMode != mode) {
ap.passwordMode = mode;
saveSettingsLocked();
@@ -373,7 +382,8 @@
if (who == null) {
throw new NullPointerException("ComponentName is null");
}
- ActiveAdmin ap = getActiveAdminForCallerLocked(who);
+ ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordLength != length) {
ap.minimumPasswordLength = length;
saveSettingsLocked();
@@ -391,7 +401,8 @@
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
- getActiveAdminForCallerLocked(null);
+ getActiveAdminForCallerLocked(null,
+ DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
return mActivePasswordMode >= getPasswordMode()
&& mActivePasswordLength >= getMinimumPasswordLength();
}
@@ -401,7 +412,8 @@
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
- getActiveAdminForCallerLocked(null);
+ getActiveAdminForCallerLocked(null,
+ DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
return mFailedPasswordAttempts;
}
}
@@ -411,7 +423,8 @@
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
- getActiveAdminForCallerLocked(null);
+ getActiveAdminForCallerLocked(null,
+ DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
mode = getPasswordMode();
if (password.length() < getMinimumPasswordLength()) {
return false;
@@ -436,7 +449,8 @@
if (who == null) {
throw new NullPointerException("ComponentName is null");
}
- ActiveAdmin ap = getActiveAdminForCallerLocked(who);
+ ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_LIMIT_UNLOCK);
if (ap.maximumTimeToUnlock != timeMs) {
ap.maximumTimeToUnlock = timeMs;
@@ -468,7 +482,8 @@
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
- getActiveAdminForCallerLocked(null);
+ getActiveAdminForCallerLocked(null,
+ DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
// STOPSHIP need to implement.
}
}
@@ -477,7 +492,8 @@
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
- getActiveAdminForCallerLocked(null);
+ getActiveAdminForCallerLocked(null,
+ DeviceAdminInfo.USES_POLICY_WIPE_DATA);
}
long ident = Binder.clearCallingIdentity();
try {
@@ -501,7 +517,8 @@
mActivePasswordMode = mode;
mActivePasswordLength = length;
mFailedPasswordAttempts = 0;
- sendAdminCommandLocked(DeviceAdmin.ACTION_PASSWORD_CHANGED);
+ sendAdminCommandLocked(DeviceAdmin.ACTION_PASSWORD_CHANGED,
+ DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -517,7 +534,8 @@
long ident = Binder.clearCallingIdentity();
try {
mFailedPasswordAttempts++;
- sendAdminCommandLocked(DeviceAdmin.ACTION_PASSWORD_FAILED);
+ sendAdminCommandLocked(DeviceAdmin.ACTION_PASSWORD_FAILED,
+ DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -533,7 +551,8 @@
long ident = Binder.clearCallingIdentity();
try {
mFailedPasswordAttempts = 0;
- sendAdminCommandLocked(DeviceAdmin.ACTION_PASSWORD_SUCCEEDED);
+ sendAdminCommandLocked(DeviceAdmin.ACTION_PASSWORD_SUCCEEDED,
+ DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index cafc804..1307972 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -2855,9 +2855,8 @@
// room left on the data partition, or a ZipException if the package
// file is malformed.
//
- private int cachePackageSharedLibsForAbiLI( PackageParser.Package pkg,
- File dataPath, File scanFile, String cpuAbi)
- throws IOException, ZipException {
+ private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
+ File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
final String apkLib = "lib/";
final int apkLibLen = apkLib.length();
@@ -2935,7 +2934,7 @@
if (mInstaller == null) {
sharedLibraryDir.mkdir();
}
- cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
+ cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir,
sharedLibraryFile);
}
}
@@ -2948,6 +2947,54 @@
return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
}
+ // Find the gdbserver executable program in a package at
+ // lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver
+ //
+ // Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
+ // or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
+ //
+ private int cachePackageGdbServerLI(PackageParser.Package pkg,
+ File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
+ File installGdbServerDir = new File(dataPath.getPath() + "/lib");
+ final String GDBSERVER = "gdbserver";
+ final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
+
+ ZipFile zipFile = new ZipFile(scanFile);
+ Enumeration<ZipEntry> entries =
+ (Enumeration<ZipEntry>) zipFile.entries();
+
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ // skip directories
+ if (entry.isDirectory()) {
+ continue;
+ }
+ String entryName = entry.getName();
+
+ if (!entryName.equals(apkGdbServerPath)) {
+ continue;
+ }
+
+ String installGdbServerPath = installGdbServerDir.getPath() +
+ "/" + GDBSERVER;
+ File installGdbServerFile = new File(installGdbServerPath);
+ if (! installGdbServerFile.exists() ||
+ installGdbServerFile.length() != entry.getSize() ||
+ installGdbServerFile.lastModified() != entry.getTime()) {
+ if (Config.LOGD) {
+ Log.d(TAG, "Caching gdbserver " + entry.getName());
+ }
+ if (mInstaller == null) {
+ installGdbServerDir.mkdir();
+ }
+ cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir,
+ installGdbServerFile);
+ }
+ return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
+ }
+ return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
+ }
+
// extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
// and copy them to /data/data/<appname>/lib.
//
@@ -2957,7 +3004,7 @@
//
private int cachePackageSharedLibsLI(PackageParser.Package pkg,
File dataPath, File scanFile) {
- final String cpuAbi = Build.CPU_ABI;
+ String cpuAbi = Build.CPU_ABI;
try {
int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
@@ -2968,7 +3015,7 @@
//
// only scan the package twice in case of ABI mismatch
if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
- String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
+ final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
if (cpuAbi2 != null) {
result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
}
@@ -2977,6 +3024,20 @@
Log.w(TAG,"Native ABI mismatch from package file");
return PackageManager.INSTALL_FAILED_INVALID_APK;
}
+
+ if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
+ cpuAbi = cpuAbi2;
+ }
+ }
+
+ // for debuggable packages, also extract gdbserver from lib/<abi>
+ // into /data/data/<appname>/lib too.
+ if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
+ (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+ int result2 = cachePackageGdbServerLI(pkg, dataPath, scanFile, cpuAbi);
+ if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
+ pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
+ }
}
} catch (ZipException e) {
Log.w(TAG, "Failed to extract data from package file", e);
@@ -2988,26 +3049,27 @@
return PackageManager.INSTALL_SUCCEEDED;
}
- private void cacheSharedLibLI(PackageParser.Package pkg,
+ private void cacheNativeBinaryLI(PackageParser.Package pkg,
ZipFile zipFile, ZipEntry entry,
- File sharedLibraryDir,
- File sharedLibraryFile) throws IOException {
+ File binaryDir,
+ File binaryFile) throws IOException {
InputStream inputStream = zipFile.getInputStream(entry);
try {
- File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
+ File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
String tempFilePath = tempFile.getPath();
- // XXX package manager can't change owner, so the lib files for
+ // XXX package manager can't change owner, so the executable files for
// now need to be left as world readable and owned by the system.
if (! FileUtils.copyToFile(inputStream, tempFile) ||
! tempFile.setLastModified(entry.getTime()) ||
FileUtils.setPermissions(tempFilePath,
FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
+ |FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH
|FileUtils.S_IROTH, -1, -1) != 0 ||
- ! tempFile.renameTo(sharedLibraryFile)) {
+ ! tempFile.renameTo(binaryFile)) {
// Failed to properly write file.
tempFile.delete();
- throw new IOException("Couldn't create cached shared lib "
- + sharedLibraryFile + " in " + sharedLibraryDir);
+ throw new IOException("Couldn't create cached binary "
+ + binaryFile + " in " + binaryDir);
}
} finally {
inputStream.close();