Merge "For mpeg4 files streamed through HTTP, cache the entire sampletable metadata chunk in memory if possible."
diff --git a/Android.mk b/Android.mk
index 7cd482c..7717c76 100644
--- a/Android.mk
+++ b/Android.mk
@@ -112,6 +112,7 @@
core/java/android/os/ICheckinService.aidl \
core/java/android/os/IMessenger.aidl \
core/java/android/os/IMountService.aidl \
+ core/java/android/os/IMountServiceObserver.aidl \
core/java/android/os/INetworkManagementService.aidl \
core/java/android/os/INetStatService.aidl \
core/java/android/os/IParentalControlCallback.aidl \
diff --git a/api/current.xml b/api/current.xml
index f73d9da..b03f826 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -20421,6 +20421,19 @@
visibility="public"
>
</method>
+<method name="getMaximumFailedPasswordsForWipe"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
<method name="getMaximumTimeToLock"
return="long"
abstract="false"
@@ -20431,8 +20444,10 @@
deprecated="not deprecated"
visibility="public"
>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
</method>
-<method name="getMinimumPasswordLength"
+<method name="getPasswordMaximumLength"
return="int"
abstract="false"
native="false"
@@ -20442,6 +20457,21 @@
deprecated="not deprecated"
visibility="public"
>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<method name="getPasswordMinimumLength"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
</method>
<method name="getPasswordMode"
return="int"
@@ -20453,6 +20483,8 @@
deprecated="not deprecated"
visibility="public"
>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
</method>
<method name="isActivePasswordSufficient"
return="boolean"
@@ -20545,7 +20577,7 @@
<parameter name="timeMs" type="long">
</parameter>
</method>
-<method name="setMinimumPasswordLength"
+<method name="setPasswordMinimumLength"
return="void"
abstract="false"
native="false"
diff --git a/awt/javax/imageio/metadata/IIOMetadataNode.java b/awt/javax/imageio/metadata/IIOMetadataNode.java
index adc6d67..efbaae8 100644
--- a/awt/javax/imageio/metadata/IIOMetadataNode.java
+++ b/awt/javax/imageio/metadata/IIOMetadataNode.java
@@ -27,6 +27,8 @@
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import org.w3c.dom.TypeInfo;
+import org.w3c.dom.UserDataHandler;
//???AWT
//import org.w3c.dom.TypeInfo;
@@ -924,6 +926,14 @@
return userObject;
}
+ public TypeInfo getSchemaTypeInfo() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object setUserData(String key, Object data, UserDataHandler handler) {
+ throw new UnsupportedOperationException();
+ }
+
/**
* Sets the user object associated with this node.
*
diff --git a/core/java/android/app/DeviceAdmin.java b/core/java/android/app/DeviceAdmin.java
index 88fdab2..b9a84b7 100644
--- a/core/java/android/app/DeviceAdmin.java
+++ b/core/java/android/app/DeviceAdmin.java
@@ -99,11 +99,10 @@
/**
* Action sent to a device administrator when the user has changed the
* password of their device. You can at this point check the characteristics
- * of the new password with {@link DevicePolicyManager#getPasswordMode()
- * DevicePolicyManager.getActivePasswordMode()} and
- * {@link DevicePolicyManager#getMinimumPasswordLength()
- * DevicePolicyManager.getMinimumPasswordLength()}. You will generally
- * handle this in {@link DeviceAdmin#onPasswordChanged(Context, Intent)}.
+ * of the new password with {@link DevicePolicyManager#isActivePasswordSufficient()
+ * DevicePolicyManager.isActivePasswordSufficient()}.
+ * You will generally
+ * handle this in {@link DeviceAdmin#onPasswordChanged}.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to receive
@@ -117,9 +116,9 @@
* Action sent to a device administrator when the user has failed at
* attempted to enter the password. You can at this point check the
* number of failed password attempts there have been with
- * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts()
+ * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts
* DevicePolicyManager.getCurrentFailedPasswordAttempts()}. You will generally
- * handle this in {@link DeviceAdmin#onPasswordFailed(Context, Intent)}.
+ * handle this in {@link DeviceAdmin#onPasswordFailed}.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
diff --git a/core/java/android/app/DeviceAdminInfo.java b/core/java/android/app/DeviceAdminInfo.java
index e50db89..50b342b 100644
--- a/core/java/android/app/DeviceAdminInfo.java
+++ b/core/java/android/app/DeviceAdminInfo.java
@@ -51,7 +51,7 @@
/**
* 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}.
+ * and {@link DevicePolicyManager#setPasswordMinimumLength}.
*
* <p>To control this policy, the device admin must have a "limit-password"
* tag in the "uses-policies" section of its meta-data.
diff --git a/core/java/android/app/DevicePolicyManager.java b/core/java/android/app/DevicePolicyManager.java
index 135851f..779db3a 100644
--- a/core/java/android/app/DevicePolicyManager.java
+++ b/core/java/android/app/DevicePolicyManager.java
@@ -89,7 +89,7 @@
/**
* Activity action: have the user enter a new password. This activity
* should be launched after using {@link #setPasswordMode(ComponentName, int)}
- * or {@link #setMinimumPasswordLength(ComponentName, int)} to have the
+ * or {@link #setPasswordMinimumLength(ComponentName, int)} to have the
* user enter a new password that meets the current requirements. You can
* use {@link #isActivePasswordSufficient()} to determine whether you need
* to have the user select a new password in order to meet the current
@@ -210,13 +210,15 @@
}
/**
- * Retrieve the current password mode that is in effect due to all
- * device admins.
+ * Retrieve the current minimum password mode for all admins
+ * or a particular one.
+ * @param admin The name of the admin component to check, or null to aggregate
+ * all admins.
*/
- public int getPasswordMode() {
+ public int getPasswordMode(ComponentName admin) {
if (mService != null) {
try {
- return mService.getPasswordMode();
+ return mService.getPasswordMode(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -244,10 +246,10 @@
* @param length The new desired minimum password length. A value of 0
* means there is no restriction.
*/
- public void setMinimumPasswordLength(ComponentName admin, int length) {
+ public void setPasswordMinimumLength(ComponentName admin, int length) {
if (mService != null) {
try {
- mService.setMinimumPasswordLength(admin, length);
+ mService.setPasswordMinimumLength(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -255,13 +257,15 @@
}
/**
- * Retrieve the current minimum password length that is in effect due to all
- * device admins.
+ * Retrieve the current minimum password length for all admins
+ * or a particular one.
+ * @param admin The name of the admin component to check, or null to aggregate
+ * all admins.
*/
- public int getMinimumPasswordLength() {
+ public int getPasswordMinimumLength(ComponentName admin) {
if (mService != null) {
try {
- return mService.getMinimumPasswordLength();
+ return mService.getPasswordMinimumLength(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -270,6 +274,17 @@
}
/**
+ * Return the maximum password length that the device supports for a
+ * particular password mode.
+ * @param mode The mode being interrogated.
+ * @return Returns the maximum length that the user can enter.
+ */
+ public int getPasswordMaximumLength(int mode) {
+ // Kind-of arbitrary.
+ return 16;
+ }
+
+ /**
* Determine whether the current password the user has set is sufficient
* to meet the policy requirements (mode, minimum length) that have been
* requested.
@@ -335,11 +350,30 @@
}
/**
+ * Retrieve the current maximum number of login attempts that are allowed
+ * before the device wipes itself, for all admins
+ * or a particular one.
+ * @param admin The name of the admin component to check, or null to aggregate
+ * all admins.
+ */
+ public int getMaximumFailedPasswordsForWipe(ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getMaximumFailedPasswordsForWipe(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return 0;
+ }
+
+ /**
* Force a new password on the user. This takes effect immediately. The
* given password must meet the current password minimum length constraint
* or it will be rejected. The given password will be accepted regardless
* of the current password mode, automatically adjusting the password mode
- * higher if needed. (The string you give here is acceptable for any mode;
+ * higher if needed to meet the requirements of all active administrators.
+ * (The string you give here is acceptable for any mode;
* if it contains only digits, that is still an acceptable alphanumeric
* password.)
*
@@ -386,13 +420,15 @@
}
/**
- * Retrieve the current maximum time to lock that is in effect due to all
- * device admins. Returns 0 if no maximum is set.
+ * Retrieve the current maximum time to unlock for all admins
+ * or a particular one.
+ * @param admin The name of the admin component to check, or null to aggregate
+ * all admins.
*/
- public long getMaximumTimeToLock() {
+ public long getMaximumTimeToLock(ComponentName admin) {
if (mService != null) {
try {
- return mService.getMaximumTimeToLock();
+ return mService.getMaximumTimeToLock(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
diff --git a/core/java/android/app/IDevicePolicyManager.aidl b/core/java/android/app/IDevicePolicyManager.aidl
index a5508cd..8d804f9 100644
--- a/core/java/android/app/IDevicePolicyManager.aidl
+++ b/core/java/android/app/IDevicePolicyManager.aidl
@@ -26,19 +26,21 @@
*/
interface IDevicePolicyManager {
void setPasswordMode(in ComponentName who, int mode);
- int getPasswordMode();
+ int getPasswordMode(in ComponentName who);
- void setMinimumPasswordLength(in ComponentName who, int length);
- int getMinimumPasswordLength();
+ void setPasswordMinimumLength(in ComponentName who, int length);
+ int getPasswordMinimumLength(in ComponentName who);
boolean isActivePasswordSufficient();
int getCurrentFailedPasswordAttempts();
+
void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num);
+ int getMaximumFailedPasswordsForWipe(in ComponentName admin);
boolean resetPassword(String password);
void setMaximumTimeToLock(in ComponentName who, long timeMs);
- long getMaximumTimeToLock();
+ long getMaximumTimeToLock(in ComponentName who);
void lockNow();
diff --git a/core/java/com/google/android/mms/util/SqliteWrapper.java b/core/java/android/database/sqlite/SqliteWrapper.java
similarity index 84%
rename from core/java/com/google/android/mms/util/SqliteWrapper.java
rename to core/java/android/database/sqlite/SqliteWrapper.java
index bcdac22..b019618 100644
--- a/core/java/com/google/android/mms/util/SqliteWrapper.java
+++ b/core/java/android/database/sqlite/SqliteWrapper.java
@@ -15,9 +15,8 @@
* limitations under the License.
*/
-package com.google.android.mms.util;
+package android.database.sqlite;
-import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -27,6 +26,10 @@
import android.util.Log;
import android.widget.Toast;
+/**
+ * @hide
+ */
+
public final class SqliteWrapper {
private static final String TAG = "SqliteWrapper";
private static final String SQLITE_EXCEPTION_DETAIL_MESSAGE
@@ -36,21 +39,6 @@
// Forbidden being instantiated.
}
- // FIXME: It looks like outInfo.lowMemory does not work well as we expected.
- // after run command: adb shell fillup -p 100, outInfo.lowMemory is still false.
- private static boolean isLowMemory(Context context) {
- if (null == context) {
- return false;
- }
-
- ActivityManager am = (ActivityManager)
- context.getSystemService(Context.ACTIVITY_SERVICE);
- ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo();
- am.getMemoryInfo(outInfo);
-
- return outInfo.lowMemory;
- }
-
// FIXME: need to optimize this method.
private static boolean isLowMemory(SQLiteException e) {
return e.getMessage().equals(SQLITE_EXCEPTION_DETAIL_MESSAGE);
diff --git a/core/java/android/os/IMountServiceObserver.aidl b/core/java/android/os/IMountServiceObserver.aidl
new file mode 100644
index 0000000..f753649
--- /dev/null
+++ b/core/java/android/os/IMountServiceObserver.aidl
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009 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.os;
+
+/**
+ * Callback class for receiving events from MountService.
+ *
+ * @hide
+ */
+interface IMountServiceObserver {
+ /**
+ * A sharing method has changed availability state.
+ *
+ * @param method The share method which has changed.
+ * @param available The share availability state.
+ */
+ void shareAvailabilityChange(String method, boolean available);
+
+ /**
+ * Media has been inserted
+ *
+ * @param label The volume label.
+ * @param path The volume mount path.
+ * @param major The backing device major number.
+ * @param minor The backing device minor number.
+ */
+ void mediaInserted(String label, String path, int major, int minor);
+
+ /**
+ * Media has been removed
+ *
+ * @param label The volume label.
+ * @param path The volume mount path.
+ * @param major The backing device major number.
+ * @param minor The backing device minor number.
+ * @param clean Indicates if the removal was clean (unmounted first).
+ */
+ void mediaRemoved(String label, String path, int major, int minor, boolean clean);
+
+ /**
+ * Volume state has changed.
+ *
+ * @param label The volume label.
+ * @param path The volume mount path.
+ * @param oldState The old state of the volume.
+ * @param newState The new state of the volume.
+ *
+ * Note: State is one of the values returned by Environment.getExternalStorageState()
+ */
+ void volumeStateChange(String label, String path, String oldState, String newState);
+
+}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index b5408ae..dedc347 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -22,6 +22,7 @@
{
void acquireWakeLock(int flags, IBinder lock, String tag);
void goToSleep(long time);
+ void goToSleepWithReason(long time, int reason);
void releaseWakeLock(IBinder lock, int flags);
void userActivity(long when, boolean noChangeLights);
void userActivityWithForce(long when, boolean noChangeLights, boolean force);
diff --git a/core/java/android/os/MountServiceObserver.java b/core/java/android/os/MountServiceObserver.java
new file mode 100644
index 0000000..3020562
--- /dev/null
+++ b/core/java/android/os/MountServiceObserver.java
@@ -0,0 +1,69 @@
+/*
+ * 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.os;
+
+/**
+ * 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 MountServiceObserver {
+ /**
+ * A sharing method has changed availability state.
+ *
+ * @param method The share method which has changed.
+ * @param available The share availability state.
+ */
+ void shareAvailabilityChange(String method, boolean available) {
+ }
+
+ /**
+ * Media has been inserted
+ *
+ * @param label The volume label.
+ * @param path The volume mount path.
+ * @param major The backing device major number.
+ * @param minor The backing device minor number.
+ */
+ void mediaInserted(String label, String path, int major, int minor) {
+ }
+
+ /**
+ * Media has been removed
+ *
+ * @param label The volume label.
+ * @param path The volume mount path.
+ * @param major The backing device major number.
+ * @param minor The backing device minor number.
+ * @param clean Indicates if the removal was clean (unmounted first).
+ */
+ void mediaRemoved(String label, String path, int major, int minor, boolean clean) {
+ }
+
+ /**
+ * Volume state has changed.
+ *
+ * @param label The volume label.
+ * @param path The volume mount path.
+ * @param oldState The old state of the volume.
+ * @param newState The new state of the volume.
+ *
+ * Note: State is one of the values returned by Environment.getExternalStorageState()
+ */
+ void volumeStateChange(String label, String path, String oldState, String newState) {
+ }
+}
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 747ae30..adeef54 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -16,8 +16,6 @@
package android.provider;
-import com.google.android.mms.util.SqliteWrapper;
-
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ContentResolver;
@@ -25,6 +23,7 @@
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
+import android.database.sqlite.SqliteWrapper;
import android.net.Uri;
import android.telephony.SmsMessage;
import android.text.TextUtils;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index bbe9c1f..21577bf 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -357,12 +357,17 @@
* previous activity, and both are on top of he wallpaper. */
public final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15 | TRANSIT_EXIT_MASK;
+ // NOTE: screen off reasons are in order of significance, with more
+ // important ones lower than less important ones.
+
+ /** Screen turned off because of a device admin */
+ public final int OFF_BECAUSE_OF_ADMIN = 1;
/** Screen turned off because of power button */
- public final int OFF_BECAUSE_OF_USER = 1;
+ public final int OFF_BECAUSE_OF_USER = 2;
/** Screen turned off because of timeout */
- public final int OFF_BECAUSE_OF_TIMEOUT = 2;
+ public final int OFF_BECAUSE_OF_TIMEOUT = 3;
/** Screen turned off because of proximity sensor */
- public final int OFF_BECAUSE_OF_PROX_SENSOR = 3;
+ public final int OFF_BECAUSE_OF_PROX_SENSOR = 4;
/**
* Magic constant to {@link IWindowManager#setRotation} to not actually
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index d018af0..39b0a63 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -499,7 +499,7 @@
static final int UPDATE_TEXT_ENTRY_MSG_ID = 15;
static final int WEBCORE_INITIALIZED_MSG_ID = 16;
static final int UPDATE_TEXTFIELD_TEXT_MSG_ID = 17;
- static final int FIND_AGAIN = 18;
+ static final int UPDATE_ZOOM_RANGE = 18;
static final int MOVE_OUT_OF_PLUGIN = 19;
static final int CLEAR_TEXT_ENTRY = 20;
static final int UPDATE_TEXT_SELECTION_MSG_ID = 21;
@@ -517,6 +517,7 @@
static final int IMMEDIATE_REPAINT_MSG_ID = 32;
static final int SET_ROOT_LAYER_MSG_ID = 33;
static final int RETURN_LABEL = 34;
+ static final int FIND_AGAIN = 35;
static final String[] HandlerDebugString = {
"REMEMBER_PASSWORD", // = 1;
@@ -536,7 +537,7 @@
"UPDATE_TEXT_ENTRY_MSG_ID", // = 15;
"WEBCORE_INITIALIZED_MSG_ID", // = 16;
"UPDATE_TEXTFIELD_TEXT_MSG_ID", // = 17;
- "FIND_AGAIN", // = 18;
+ "UPDATE_ZOOM_RANGE", // = 18;
"MOVE_OUT_OF_PLUGIN", // = 19;
"CLEAR_TEXT_ENTRY", // = 20;
"UPDATE_TEXT_SELECTION_MSG_ID", // = 21;
@@ -552,7 +553,8 @@
"DOM_FOCUS_CHANGED", // = 31;
"IMMEDIATE_REPAINT_MSG_ID", // = 32;
"SET_ROOT_LAYER_MSG_ID", // = 33;
- "RETURN_LABEL" // = 34;
+ "RETURN_LABEL", // = 34;
+ "FIND_AGAIN" // = 35;
};
// If the site doesn't use the viewport meta tag to specify the viewport,
@@ -5587,7 +5589,7 @@
// exclude INVAL_RECT_MSG_ID since it is frequently output
if (DebugFlags.WEB_VIEW && msg.what != INVAL_RECT_MSG_ID) {
Log.v(LOGTAG, msg.what < REMEMBER_PASSWORD || msg.what
- > RETURN_LABEL ? Integer.toString(msg.what)
+ > FIND_AGAIN ? Integer.toString(msg.what)
: HandlerDebugString[msg.what - REMEMBER_PASSWORD]);
}
if (mWebViewCore == null) {
@@ -5683,6 +5685,14 @@
case SPAWN_SCROLL_TO_MSG_ID:
spawnContentScrollTo(msg.arg1, msg.arg2);
break;
+ case UPDATE_ZOOM_RANGE: {
+ WebViewCore.RestoreState restoreState
+ = (WebViewCore.RestoreState) msg.obj;
+ // mScrollX contains the new minPrefWidth
+ updateZoomRange(restoreState, getViewWidth(),
+ restoreState.mScrollX, false);
+ break;
+ }
case NEW_PICTURE_MSG_ID: {
WebSettings settings = mWebViewCore.getSettings();
// called for new content
@@ -5695,32 +5705,8 @@
boolean hasRestoreState = restoreState != null;
if (hasRestoreState) {
mInZoomOverview = false;
- if (restoreState.mMinScale == 0) {
- if (restoreState.mMobileSite) {
- if (draw.mMinPrefWidth >
- Math.max(0, draw.mViewPoint.x)) {
- mMinZoomScale = (float) viewWidth
- / draw.mMinPrefWidth;
- mMinZoomScaleFixed = false;
- mInZoomOverview = useWideViewport &&
- settings.getLoadWithOverviewMode();
- } else {
- mMinZoomScale = restoreState.mDefaultScale;
- mMinZoomScaleFixed = true;
- }
- } else {
- mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
- mMinZoomScaleFixed = false;
- }
- } else {
- mMinZoomScale = restoreState.mMinScale;
- mMinZoomScaleFixed = true;
- }
- if (restoreState.mMaxScale == 0) {
- mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
- } else {
- mMaxZoomScale = restoreState.mMaxScale;
- }
+ updateZoomRange(restoreState, viewSize.x,
+ draw.mMinPrefWidth, true);
if (mInitialScaleInPercent > 0) {
setNewZoomScale(mInitialScaleInPercent / 100.0f,
mInitialScaleInPercent != mTextWrapScale * 100,
@@ -6411,6 +6397,37 @@
new InvokeListBox(array, enabledArray, selectedArray));
}
+ private void updateZoomRange(WebViewCore.RestoreState restoreState,
+ int viewWidth, int minPrefWidth, boolean updateZoomOverview) {
+ if (restoreState.mMinScale == 0) {
+ if (restoreState.mMobileSite) {
+ if (minPrefWidth > Math.max(0, viewWidth)) {
+ mMinZoomScale = (float) viewWidth / minPrefWidth;
+ mMinZoomScaleFixed = false;
+ if (updateZoomOverview) {
+ WebSettings settings = getSettings();
+ mInZoomOverview = settings.getUseWideViewPort() &&
+ settings.getLoadWithOverviewMode();
+ }
+ } else {
+ mMinZoomScale = restoreState.mDefaultScale;
+ mMinZoomScaleFixed = true;
+ }
+ } else {
+ mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
+ mMinZoomScaleFixed = false;
+ }
+ } else {
+ mMinZoomScale = restoreState.mMinScale;
+ mMinZoomScaleFixed = true;
+ }
+ if (restoreState.mMaxScale == 0) {
+ mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
+ } else {
+ mMaxZoomScale = restoreState.mMaxScale;
+ }
+ }
+
/*
* Request a dropdown menu for a listbox with single selection or a single
* <select> element.
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 1e21cb4..310721f 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2053,7 +2053,19 @@
}
// if mViewportWidth is 0, it means device-width, always update.
- if (mViewportWidth != 0 && !updateRestoreState) return;
+ if (mViewportWidth != 0 && !updateRestoreState) {
+ RestoreState restoreState = new RestoreState();
+ restoreState.mMinScale = mViewportMinimumScale / 100.0f;
+ restoreState.mMaxScale = mViewportMaximumScale / 100.0f;
+ restoreState.mDefaultScale = adjust;
+ // as mViewportWidth is not 0, it is not mobile site.
+ restoreState.mMobileSite = false;
+ // for non-mobile site, we don't need minPrefWidth, set it as 0
+ restoreState.mScrollX = 0;
+ Message.obtain(mWebView.mPrivateHandler,
+ WebView.UPDATE_ZOOM_RANGE, restoreState).sendToTarget();
+ return;
+ }
// now notify webview
// webViewWidth refers to the width in the view system
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 4cc3b9e..0078fec 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -815,9 +815,19 @@
* @param dy the number of pixels to scroll by on the Y axis
*/
public final void smoothScrollBy(int dx, int dy) {
+ if (getChildCount() == 0) {
+ // Nothing to do.
+ return;
+ }
long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
if (duration > ANIMATED_SCROLL_GAP) {
- mScroller.startScroll(mScrollX, mScrollY, dx, dy);
+ final int width = getWidth() - mPaddingRight - mPaddingLeft;
+ final int right = getChildAt(0).getWidth();
+ final int maxX = Math.max(0, right - width);
+ final int scrollX = mScrollX;
+ dx = Math.max(0, Math.min(scrollX + dx, maxX)) - scrollX;
+
+ mScroller.startScroll(scrollX, mScrollY, dx, 0);
awakenScrollBars(mScroller.getDuration());
invalidate();
} else {
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index 3fd5dcc..b22ae3c 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -49,7 +49,7 @@
public OverScroller(Context context) {
mDefaultScroller = new Scroller(context);
- mDecelScroller = new Scroller(context, new DecelerateInterpolator(3.f));
+ mDecelScroller = new Scroller(context, new DecelerateInterpolator());
mAccelDecelScroller = new Scroller(context, new AccelerateDecelerateInterpolator());
mCurrScroller = mDefaultScroller;
}
@@ -216,7 +216,7 @@
/**
* Start scrolling by providing a starting point and the distance to travel.
* The scroll will use the default value of 250 milliseconds for the
- * duration.
+ * duration. This version does not spring back to boundaries.
*
* @param startX Starting horizontal scroll offset in pixels. Positive
* numbers will scroll the content to the left.
@@ -228,13 +228,45 @@
* content up.
*/
public void startScroll(int startX, int startY, int dx, int dy) {
+ final int minX = Math.min(startX, startX + dx);
+ final int maxX = Math.max(startX, startX + dx);
+ final int minY = Math.min(startY, startY + dy);
+ final int maxY = Math.max(startY, startY + dy);
+ startScroll(startX, startY, dx, dy, minX, maxX, minY, maxY);
+ }
+
+ /**
+ * Start scrolling by providing a starting point and the distance to travel.
+ * The scroll will use the default value of 250 milliseconds for the
+ * duration. This version will spring back to the provided boundaries if
+ * the scroll value would take it too far.
+ *
+ * @param startX Starting horizontal scroll offset in pixels. Positive
+ * numbers will scroll the content to the left.
+ * @param startY Starting vertical scroll offset in pixels. Positive numbers
+ * will scroll the content up.
+ * @param dx Horizontal distance to travel. Positive numbers will scroll the
+ * content to the left.
+ * @param dy Vertical distance to travel. Positive numbers will scroll the
+ * content up.
+ * @param minX Minimum X value. The scroller will not scroll past this
+ * point.
+ * @param maxX Maximum X value. The scroller will not scroll past this
+ * point.
+ * @param minY Minimum Y value. The scroller will not scroll past this
+ * point.
+ * @param maxY Maximum Y value. The scroller will not scroll past this
+ * point.
+ */
+ public void startScroll(int startX, int startY, int dx, int dy,
+ int minX, int maxX, int minY, int maxY) {
mCurrScroller.abortAnimation();
mCurrScroller = mDefaultScroller;
mScrollMode = MODE_DEFAULT;
- mMinimumX = Math.min(startX, startX + dx);
- mMinimumY = Math.min(startY, startY + dy);
- mMaximumX = Math.max(startX, startX + dx);
- mMaximumY = Math.max(startY, startY + dy);
+ mMinimumX = minX;
+ mMaximumX = maxX;
+ mMinimumY = minY;
+ mMaximumY = maxY;
mCurrScroller.startScroll(startX, startY, dx, dy);
}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 62797f3..4a1d871 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -817,9 +817,19 @@
* @param dy the number of pixels to scroll by on the Y axis
*/
public final void smoothScrollBy(int dx, int dy) {
+ if (getChildCount() == 0) {
+ // Nothing to do.
+ return;
+ }
long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
if (duration > ANIMATED_SCROLL_GAP) {
- mScroller.startScroll(mScrollX, mScrollY, dx, dy);
+ final int height = getHeight() - mPaddingBottom - mPaddingTop;
+ final int bottom = getChildAt(0).getHeight();
+ final int maxY = Math.max(0, bottom - height);
+ final int scrollY = mScrollY;
+ dy = Math.max(0, Math.min(scrollY + dy, maxY)) - scrollY;
+
+ mScroller.startScroll(mScrollX, scrollY, 0, dy);
awakenScrollBars(mScroller.getDuration());
invalidate();
} else {
diff --git a/core/java/com/android/internal/app/UsbStorageActivity.java b/core/java/com/android/internal/app/UsbStorageActivity.java
index b8a2136..37ea352 100644
--- a/core/java/com/android/internal/app/UsbStorageActivity.java
+++ b/core/java/com/android/internal/app/UsbStorageActivity.java
@@ -16,7 +16,7 @@
package com.android.internal.app;
-import android.app.AlertDialog;
+import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -28,16 +28,23 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.widget.ImageView;
+import android.widget.Button;
+import android.widget.TextView;
import android.widget.Toast;
+import android.view.View;
/**
* This activity is shown to the user for him/her to enable USB mass storage
* on-demand (that is, when the USB cable is connected). It uses the alert
* dialog style. It will be launched from a notification.
*/
-public class UsbStorageActivity extends AlertActivity implements DialogInterface.OnClickListener {
-
- private static final int POSITIVE_BUTTON = AlertDialog.BUTTON1;
+public class UsbStorageActivity extends Activity {
+ private Button mMountButton;
+ private Button mUnmountButton;
+ private TextView mBanner;
+ private TextView mMessage;
+ private ImageView mIcon;
/** Used to detect when the USB cable is unplugged, so we can call finish() */
private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
@@ -53,16 +60,49 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // Set up the "dialog"
- final AlertController.AlertParams p = mAlertParams;
- p.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
- p.mTitle = getString(com.android.internal.R.string.usb_storage_title);
- p.mMessage = getString(com.android.internal.R.string.usb_storage_message);
- p.mPositiveButtonText = getString(com.android.internal.R.string.usb_storage_button_mount);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(com.android.internal.R.string.usb_storage_button_unmount);
- p.mNegativeButtonListener = this;
- setupAlert();
+ setTitle(getString(com.android.internal.R.string.usb_storage_activity_title));
+
+ setContentView(com.android.internal.R.layout.usb_storage_activity);
+
+ mIcon = (ImageView) findViewById(com.android.internal.R.id.icon);
+ mBanner = (TextView) findViewById(com.android.internal.R.id.banner);
+ mMessage = (TextView) findViewById(com.android.internal.R.id.message);
+
+ mMountButton = (Button) findViewById(com.android.internal.R.id.mount_button);
+ mMountButton.setOnClickListener(
+ new View.OnClickListener() {
+ public void onClick(View v) {
+ mountAsUsbStorage();
+ // TODO: replace with forthcoming MountService callbacks
+ switchDisplay(true);
+ }
+ });
+
+ mUnmountButton = (Button) findViewById(com.android.internal.R.id.unmount_button);
+ mUnmountButton.setOnClickListener(
+ new View.OnClickListener() {
+ public void onClick(View v) {
+ stopUsbStorage();
+ // TODO: replace with forthcoming MountService callbacks
+ switchDisplay(false);
+ }
+ });
+ }
+
+ private void switchDisplay(boolean usbStorageInUse) {
+ if (usbStorageInUse) {
+ mUnmountButton.setVisibility(View.VISIBLE);
+ mMountButton.setVisibility(View.GONE);
+ mIcon.setImageResource(com.android.internal.R.drawable.usb_android_connected);
+ mBanner.setText(com.android.internal.R.string.usb_storage_stop_title);
+ mMessage.setText(com.android.internal.R.string.usb_storage_stop_message);
+ } else {
+ mUnmountButton.setVisibility(View.GONE);
+ mMountButton.setVisibility(View.VISIBLE);
+ mIcon.setImageResource(com.android.internal.R.drawable.usb_android);
+ mBanner.setText(com.android.internal.R.string.usb_storage_title);
+ mMessage.setText(com.android.internal.R.string.usb_storage_message);
+ }
}
@Override
@@ -70,6 +110,18 @@
super.onResume();
registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+
+ boolean umsOn = false;
+ try {
+ IMountService mountService = IMountService.Stub.asInterface(ServiceManager
+ .getService("mount"));
+ if (mountService != null) {
+ umsOn = mountService.getMassStorageEnabled();
+ }
+ } catch (android.os.RemoteException exc) {
+ // pass
+ }
+ switchDisplay(umsOn);
}
@Override
@@ -79,19 +131,6 @@
unregisterReceiver(mBatteryReceiver);
}
- /**
- * {@inheritDoc}
- */
- public void onClick(DialogInterface dialog, int which) {
-
- if (which == POSITIVE_BUTTON) {
- mountAsUsbStorage();
- }
-
- // No matter what, finish the activity
- finish();
- }
-
private void mountAsUsbStorage() {
IMountService mountService = IMountService.Stub.asInterface(ServiceManager
.getService("mount"));
@@ -108,6 +147,22 @@
}
}
+ private void stopUsbStorage() {
+ IMountService mountService = IMountService.Stub.asInterface(ServiceManager
+ .getService("mount"));
+ if (mountService == null) {
+ showStoppingError();
+ return;
+ }
+
+ try {
+ mountService.setMassStorageEnabled(false);
+ } catch (RemoteException e) {
+ showStoppingError();
+ return;
+ }
+ }
+
private void handleBatteryChanged(Intent intent) {
int pluggedType = intent.getIntExtra("plugged", 0);
if (pluggedType == 0) {
@@ -120,5 +175,10 @@
Toast.makeText(this, com.android.internal.R.string.usb_storage_error_message,
Toast.LENGTH_LONG).show();
}
+
+ private void showStoppingError() {
+ Toast.makeText(this, com.android.internal.R.string.usb_storage_stop_error_message,
+ Toast.LENGTH_LONG).show();
+ }
}
diff --git a/core/java/com/android/internal/app/UsbStorageStopActivity.java b/core/java/com/android/internal/app/UsbStorageStopActivity.java
deleted file mode 100644
index 557a523..0000000
--- a/core/java/com/android/internal/app/UsbStorageStopActivity.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2007 Google Inc.
- *
- * 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.internal.app;
-
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IMountService;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.widget.Toast;
-
-/**
- * This activity is shown to the user for him/her to disable USB mass storage.
- * It uses the alert dialog style. It will be launched from a notification.
- */
-public class UsbStorageStopActivity extends AlertActivity implements DialogInterface.OnClickListener {
-
- private static final int POSITIVE_BUTTON = AlertDialog.BUTTON1;
-
- /** Used to detect when the USB cable is unplugged, so we can call finish() */
- private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction() == Intent.ACTION_BATTERY_CHANGED) {
- handleBatteryChanged(intent);
- }
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Set up the "dialog"
- final AlertController.AlertParams p = mAlertParams;
- p.mIconId = com.android.internal.R.drawable.ic_dialog_alert;
- p.mTitle = getString(com.android.internal.R.string.usb_storage_stop_title);
- p.mMessage = getString(com.android.internal.R.string.usb_storage_stop_message);
- p.mPositiveButtonText = getString(com.android.internal.R.string.usb_storage_stop_button_mount);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(com.android.internal.R.string.usb_storage_stop_button_unmount);
- p.mNegativeButtonListener = this;
- setupAlert();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- unregisterReceiver(mBatteryReceiver);
- }
-
- /**
- * {@inheritDoc}
- */
- public void onClick(DialogInterface dialog, int which) {
-
- if (which == POSITIVE_BUTTON) {
- stopUsbStorage();
- }
-
- // No matter what, finish the activity
- finish();
- }
-
- private void stopUsbStorage() {
- IMountService mountService = IMountService.Stub.asInterface(ServiceManager
- .getService("mount"));
- if (mountService == null) {
- showStoppingError();
- return;
- }
-
- try {
- mountService.setMassStorageEnabled(false);
- } catch (RemoteException e) {
- showStoppingError();
- return;
- }
- }
-
- private void handleBatteryChanged(Intent intent) {
- int pluggedType = intent.getIntExtra("plugged", 0);
- if (pluggedType == 0) {
- // It was disconnected from the plug, so finish
- finish();
- }
- }
-
- private void showStoppingError() {
- Toast.makeText(this, com.android.internal.R.string.usb_storage_stop_error_message,
- Toast.LENGTH_LONG).show();
- }
-
-}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index bd41a13..6347146 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -122,7 +122,7 @@
}
public int getRequestedMinimumPasswordLength() {
- return mDevicePolicyManager.getMinimumPasswordLength();
+ return mDevicePolicyManager.getPasswordMinimumLength(null);
}
/**
@@ -132,7 +132,7 @@
* @return
*/
public int getRequestedPasswordMode() {
- int policyMode = mDevicePolicyManager.getPasswordMode();
+ int policyMode = mDevicePolicyManager.getPasswordMode(null);
switch (policyMode) {
case DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC:
return MODE_PASSWORD;
diff --git a/core/java/com/google/android/mms/package.html b/core/java/com/google/android/mms/package.html
deleted file mode 100755
index c9f96a6..0000000
--- a/core/java/com/google/android/mms/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/com/google/android/mms/pdu/package.html b/core/java/com/google/android/mms/pdu/package.html
deleted file mode 100755
index c9f96a6..0000000
--- a/core/java/com/google/android/mms/pdu/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/com/google/android/mms/util/package.html b/core/java/com/google/android/mms/util/package.html
deleted file mode 100755
index c9f96a6..0000000
--- a/core/java/com/google/android/mms/util/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 54e15a5..665088a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1240,7 +1240,6 @@
</intent-filter>
</activity>
<activity android:name="com.android.internal.app.UsbStorageActivity"
- android:theme="@style/Theme.Dialog.Alert"
android:excludeFromRecents="true">
</activity>
<activity android:name="com.android.internal.app.UsbStorageStopActivity"
diff --git a/core/res/res/drawable-hdpi/search_plate_global.9.png b/core/res/res/drawable-hdpi/search_plate_global.9.png
index 32c6dc3..e9f4f12 100644
--- a/core/res/res/drawable-hdpi/search_plate_global.9.png
+++ b/core/res/res/drawable-hdpi/search_plate_global.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/search_source_selector_indicator.png b/core/res/res/drawable-hdpi/search_source_selector_indicator.png
index b93a0c0..e81d9ac 100644
--- a/core/res/res/drawable-hdpi/search_source_selector_indicator.png
+++ b/core/res/res/drawable-hdpi/search_source_selector_indicator.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/usb_android.png b/core/res/res/drawable-hdpi/usb_android.png
new file mode 100644
index 0000000..8153ec4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/usb_android.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/usb_android_connected.png b/core/res/res/drawable-hdpi/usb_android_connected.png
new file mode 100644
index 0000000..6449b7c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/usb_android_connected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/search_plate_global.9.png b/core/res/res/drawable-mdpi/search_plate_global.9.png
index 1cad902..bb7400e 100644
--- a/core/res/res/drawable-mdpi/search_plate_global.9.png
+++ b/core/res/res/drawable-mdpi/search_plate_global.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/search_source_selector_indicator.png b/core/res/res/drawable-mdpi/search_source_selector_indicator.png
index 26bf18a..b3efef2 100644
--- a/core/res/res/drawable-mdpi/search_source_selector_indicator.png
+++ b/core/res/res/drawable-mdpi/search_source_selector_indicator.png
Binary files differ
diff --git a/core/res/res/layout-land/usb_storage_activity.xml b/core/res/res/layout-land/usb_storage_activity.xml
new file mode 100644
index 0000000..d714479
--- /dev/null
+++ b/core/res/res/layout-land/usb_storage_activity.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:padding="18dip"
+ android:orientation="horizontal"
+ >
+
+ <ImageView android:id="@+id/icon"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentTop="true"
+ android:layout_height="wrap_content"
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ android:src="@drawable/usb_android" />
+
+ <RelativeLayout
+ android:layout_height="wrap_content"
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ >
+
+ <TextView android:id="@+id/banner"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/icon"
+ android:layout_marginTop="10dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="24sp"
+ android:gravity="center"
+ android:text="@string/usb_storage_title" />
+
+ <TextView android:id="@+id/message"
+ android:layout_below="@id/banner"
+ android:layout_marginTop="10dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="14sp"
+ android:gravity="center"
+ android:text="@string/usb_storage_message" />
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/message"
+ android:layout_marginTop="20dip"
+ >
+
+ <Button android:id="@+id/mount_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="18dip"
+ android:paddingRight="18dip"
+ android:text="@string/usb_storage_button_mount"
+ />
+ <Button android:id="@+id/unmount_button"
+ android:visibility="gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="18dip"
+ android:paddingRight="18dip"
+ android:text="@string/usb_storage_stop_button_mount"
+ />
+
+ </RelativeLayout>
+ </RelativeLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
index 2fa7aaa..244afbe 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
@@ -23,6 +23,28 @@
android:background="@android:color/background_dark"
>
+ <!-- header text ('Enter Pin Code') -->
+ <TextView android:id="@+id/headerText"
+ android:layout_above="@+id/carrier"
+ android:layout_centerHorizontal="true"
+ android:layout_marginBottom="30dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="24sp"
+ />
+
+ <!-- Carrier info -->
+ <TextView android:id="@+id/carrier"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_above="@+id/pinDisplayGroup"
+ android:layout_marginTop="9dip"
+ android:gravity="left|bottom"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ />
+
<!-- displays dots as user enters pin -->
<LinearLayout android:id="@+id/pinDisplayGroup"
android:orientation="horizontal"
@@ -60,16 +82,6 @@
</LinearLayout>
- <!-- header text ('Enter Pin Code') -->
- <TextView android:id="@+id/headerText"
- android:layout_above="@id/pinDisplayGroup"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="30dip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="24sp"
- />
-
<LinearLayout
android:orientation="horizontal"
android:layout_alignParentBottom="true"
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
index 1f7f8f7..009148f 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
@@ -33,9 +33,19 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
- android:lines="2"
+ android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"/>
+ <!-- Carrier info -->
+ <TextView android:id="@+id/carrier"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="9dip"
+ android:gravity="center"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
+
<!-- password entry -->
<LinearLayout
android:layout_width="match_parent"
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index f9566d8..b404955 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -28,7 +28,7 @@
android:background="#70000000"
android:gravity="center_horizontal"
android:id="@+id/root">
-
+
<TextView
android:id="@+id/carrier"
android:layout_width="wrap_content"
@@ -37,6 +37,9 @@
android:layout_alignParentRight="true"
android:layout_marginTop="10dip"
android:layout_marginRight="8dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:gravity="right|bottom"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
@@ -144,7 +147,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
- android:layout_marginBottom="80dip"
+ android:layout_marginBottom="80dip"
/>
</RelativeLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 9965554..6ee659c 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -27,7 +27,7 @@
android:orientation="horizontal"
android:background="#70000000"
android:id="@+id/root">
-
+
<!-- left side -->
<RelativeLayout
android:layout_width="0dip"
@@ -42,6 +42,9 @@
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="20dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:gravity="right|bottom"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index 58f36ed..c1b406f 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -54,6 +54,9 @@
android:textSize="17sp"
android:drawablePadding="4dip"
android:layout_marginTop="32dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:gravity="right|bottom"
/>
<com.android.internal.widget.DigitalClock android:id="@+id/time"
android:layout_width="wrap_content"
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index ac6cf19..16cd48c 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -41,6 +41,10 @@
android:layout_marginTop="6dip"
android:layout_alignParentRight="true"
android:layout_marginRight="8dip"
+ android:layout_toRightOf="@+id/time"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:gravity="right|bottom"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
@@ -93,7 +97,7 @@
android:layout_marginLeft="24dip"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
-
+
</RelativeLayout>
<View
diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml
index 12285fd..2e93a39 100644
--- a/core/res/res/layout/search_bar.xml
+++ b/core/res/res/layout/search_bar.xml
@@ -33,10 +33,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:paddingLeft="12dip"
- android:paddingRight="12dip"
- android:paddingTop="7dip"
- android:paddingBottom="16dip"
+ android:paddingLeft="4dip"
+ android:paddingRight="4dip"
+ android:paddingTop="4dip"
android:background="@drawable/search_plate_global" >
<!-- This is actually used for the badge icon *or* the badge label (or neither) -->
@@ -63,10 +62,11 @@
<view class="android.app.SearchDialog$SearchAutoComplete"
android:id="@+id/search_src_text"
- android:background="@drawable/textfield_search"
+ android:background="@drawable/edit_text"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1.0"
+ android:layout_marginLeft="4dip"
android:paddingLeft="8dip"
android:paddingRight="6dip"
android:drawablePadding="2dip"
@@ -86,13 +86,15 @@
android:background="@drawable/btn_search_dialog"
android:layout_width="wrap_content"
android:layout_height="match_parent"
+ android:visibility="gone"
/>
<ImageButton
android:id="@+id/search_voice_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_marginLeft="8dip"
+ android:layout_marginLeft="4dip"
+ android:layout_marginBottom="4dip"
android:background="@drawable/btn_search_dialog_voice"
android:src="@android:drawable/ic_btn_speak_now"
/>
diff --git a/core/res/res/layout/search_source_selector.xml b/core/res/res/layout/search_source_selector.xml
index c69dfc0..9312b08 100644
--- a/core/res/res/layout/search_source_selector.xml
+++ b/core/res/res/layout/search_source_selector.xml
@@ -16,10 +16,11 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="48dip"
+ android:layout_width="42dip"
android:layout_height="match_parent"
+ android:layout_marginBottom="2dip"
android:foreground="@drawable/search_source_selector_indicator"
- android:foregroundGravity="bottom|right"
+ android:foregroundGravity="bottom|center_horizontal"
>
<ImageButton
@@ -27,6 +28,7 @@
android:background="@drawable/search_source_selector_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:layout_marginBottom="6dip"
android:scaleType="centerInside"
android:focusable="true"
android:clickable="true"
diff --git a/core/res/res/layout/usb_storage_activity.xml b/core/res/res/layout/usb_storage_activity.xml
new file mode 100644
index 0000000..86bfadb
--- /dev/null
+++ b/core/res/res/layout/usb_storage_activity.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:padding="18dip"
+ >
+
+ <ImageView android:id="@+id/icon"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentTop="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/usb_android" />
+
+ <TextView android:id="@+id/banner"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/icon"
+ android:layout_marginTop="10dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="24sp"
+ android:gravity="center"
+ android:text="@string/usb_storage_title" />
+
+ <TextView android:id="@+id/message"
+ android:layout_below="@id/banner"
+ android:layout_marginTop="10dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="14sp"
+ android:gravity="center"
+ android:text="@string/usb_storage_message" />
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/message"
+ android:layout_marginTop="20dip"
+ >
+
+ <Button android:id="@+id/mount_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="18dip"
+ android:paddingRight="18dip"
+ android:text="@string/usb_storage_button_mount"
+ />
+ <Button android:id="@+id/unmount_button"
+ android:visibility="gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="18dip"
+ android:paddingRight="18dip"
+ android:text="@string/usb_storage_stop_button_mount"
+ />
+
+ </RelativeLayout>
+</RelativeLayout>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 42553d4..8f97c13 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2008,21 +2008,23 @@
<string name="googlewebcontenthelper_loading">Loading\u2026</string>
<!-- USB storage dialog strings -->
- <!-- This is the label for the activity, and should never be visible to the user. -->
+ <!-- This is the title for the activity's window. -->
+ <string name="usb_storage_activity_title">USB Mass Storage</string>
+
<!-- See USB_STORAGE. USB_STORAGE_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to mount. This is the title. -->
<string name="usb_storage_title">USB connected</string>
<!-- See USB_STORAGE. This is the message. -->
- <string name="usb_storage_message">You have connected your phone to your computer via USB. Select \"Mount\" if you want to copy files between your computer and your phone\'s SD card.</string>
+ <string name="usb_storage_message">You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\u2018s SD card.</string>
<!-- See USB_STORAGE. This is the button text to mount the phone on the computer. -->
- <string name="usb_storage_button_mount">Mount</string>
- <!-- See USB_STORAGE. This is the button text to ignore the plugging in of the phone.. -->
- <string name="usb_storage_button_unmount">Don\'t mount</string>
+ <string name="usb_storage_button_mount">Turn on USB storage</string>
<!-- See USB_STORAGE_DIALOG. If there was an error mounting, this is the text. -->
<string name="usb_storage_error_message">There is a problem using your SD card for USB storage.</string>
<!-- USB_STORAGE: When the user connects the phone to a computer via USB, we show a notification asking if he wants to share files across. This is the title -->
<string name="usb_storage_notification_title">USB connected</string>
<!-- See USB_STORAGE. This is the message. -->
<string name="usb_storage_notification_message">Select to copy files to/from your computer.</string>
+
+
<!-- USB_STORAGE_STOP: While USB storage is enabled, we show a notification dialog asking if he wants to stop. This is the title -->
<string name="usb_storage_stop_notification_title">Turn off USB storage</string>
<!-- See USB_STORAGE. This is the message. -->
@@ -2031,15 +2033,13 @@
<!-- USB storage stop dialog strings -->
<!-- This is the label for the activity, and should never be visible to the user. -->
<!-- See USB_STORAGE_STOP. USB_STORAGE_STOP_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to stop usb storage. This is the title. -->
- <string name="usb_storage_stop_title">Turn off USB storage</string>
+ <string name="usb_storage_stop_title">USB storage in use</string>
<!-- See USB_STORAGE_STOP. This is the message. -->
- <string name="usb_storage_stop_message">Before turning off USB storage, make sure you have unmounted on the USB host. Select \"Turn Off\" to turn off USB storage.</string>
+ <string name="usb_storage_stop_message">Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s SD card from your computer.</string>
<!-- See USB_STORAGE_STOP. This is the button text to stop usb storage. -->
- <string name="usb_storage_stop_button_mount">Turn Off</string>
- <!-- See USB_STORAGE_STOP. This is the button text to cancel stoping usb storage. -->
- <string name="usb_storage_stop_button_unmount">Cancel</string>
+ <string name="usb_storage_stop_button_mount">Turn off USB storage</string>
<!-- See USB_STORAGE_STOP_DIALOG. If there was an error stopping, this is the text. -->
- <string name="usb_storage_stop_error_message">We\'ve encountered a problem turning off USB storage. Check to make sure you have unmounted the USB host, then try again.</string>
+ <string name="usb_storage_stop_error_message">There was a problem turning off USB storage. Check to make sure you have unmounted the USB host, then try again.</string>
<!-- External media format dialog strings -->
<!-- This is the label for the activity, and should never be visible to the user. -->
diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index 643d307..0fad4c6 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -260,7 +260,7 @@
same physical size on all screens in a given configuration. </p> -->
<p>Although the platform currently supports the nine possible size-density
-configurations listed in the table, you do not necessarily need to custom
+configurations listed in the table, you do not necessarily need to create custom
resources for each one of them. The platform provides robust compatibility
features, described in the sections below, that can handle most of the work of
rendering your application on the current device screen, provided that the UI is
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index d7fc563..8594452 100644
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -14,23 +14,44 @@
<dd><code><a
href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code></dd>
+ <div class="sidebox-wrapper">
+ <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
+ <div id="qv-sub-rule">
+ <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;">
+ <p style="color:#669999;">Android Market and <uses-feature> elements</p>
+ <p>Android Market filters the applications that are visible to users, so
+that users can see and download only those applications that are compatible with their
+devices. One of the ways Market filters applications is by feature compatibility.</p>
+
+<p style="margin-top:1em;">To do this, Market checks the
+<code><uses-feature></code> elements in each application's manifest, to
+establish the app's feature needs. Market then shows or hides the application to
+each user, based on a comparison with the features available on the user's
+device. </p>
+
+<p style="margin-top:1em;">By specifying the features your application requires,
+you enable Android Market to present your application only to users whose
+devices meet the application's feature requirements, rather than presenting it
+to all users. </p>
+</div>
+</div>
+
<dt>description:</dt>
-<dd>This element declares a specific feature used by the application.
-Android provides some features that may not be equally supported by all
-Android devices. In a manner similar to the <code><a
-href="uses-sdk-element.html"><uses-sdk></a></code>
-element, this element allows an application to specify which device-variable
-features it uses. In this way, the application
-will not be installed on devices that do not offer the feature.</p>
+<dd>This element declares a specific feature used by the application. Android
+provides some features that may not be equally supported by all Android devices.
+In a manner similar to the <a
+href="uses-sdk-element.html">{@code <uses-sdk>}</a> element, this element
+allows an application to specify which device-variable features it uses. For
+example, an application might specify that it requires a camera with auto-focus
+capabilities.</p>
-<p>For example, an application might specify that it requires a camera with auto-focus capabilities.
-If a device does not provide a camera with auto-focus, then it will not allow
-installation of the application.</p>
-
-<p>In order to maintain strict device compatibility, it's very important that you use
-this element to declare all applicable features (listed below) that your application uses. Failure
-to declare a feature may result in your application being installed on a device
-that does not support the feature and your application failing.</p>
+<p>Declaring a {@code <uses-feature>} element is informational only, meaning
+that the Android system itself does not check for matching feature support on
+the device before installing an application. However, note that other services
+(such as Android Market) or applications may check your application's
+{@code <uses-feature>} declarations as part of handling or interacting
+with your application. For this reason, it's very important that you declare all of
+the features (from the list below) that your application uses. </p>
<p>For some features, there may exist a specfic attribute that allows you to define
a version of the feature, such as the version of Open GL used (declared with
@@ -38,11 +59,12 @@
exist for a device, such as a camera, are declared using the
<a href="#name">{@code name}</a> attribute.</p>
-<p>Any software or hardware features that may vary among Android-powered
-devices will be listed on this page among the attributes below. If you see any features
-here that you use in your application, you should include a {@code
-<uses-feature>} element for each one. For example, if your application uses the device
-camera, then you should include the following in your {@code AndroidManifest.xml}:</p>
+<p>Any software or hardware features that may vary among Android-powered devices
+will be listed on this page among the attributes below. If you see any features
+here that you use in your application, you should include a
+{@code <uses-feature>} element for each one. For example, if your
+application uses the device camera, then you should include the following in
+your {@code AndroidManifest.xml}:</p>
<pre>
<uses-feature android:name="android.hardware.camera" />
@@ -77,10 +99,29 @@
<dd>
<dl class="attr">
<dt><a name="glEsVersion"></a>{@code android:glEsVersion}</dt>
- <dd>The GLES version needed by the application.
- The higher 16 bits represent the major number and the lower 16 bits
- represent the minor number. For example, for GL 1.2,
- the value should be set as {@code 0x00010002}.
+ <dd>The OpenGL ES version required by the application. The higher 16 bits
+represent the major number and the lower 16 bits represent the minor number. For
+example, to specify OpenGL ES version 2.0, you would set the value as
+"0x00020000". To specify OpenGL ES 2.1, if/when such a version were made
+available, you would set the value as "0x00020001".
+
+ <p>An application should specify at most one <code>android:glEsVersion</code>
+attribute in its manifest. If it specifies more than one, the
+<code>android:glEsVersion</code> with the numerically highest value is used and
+any other values are ignored.</p>
+
+ <p>If an application does not specify an <code>android:glEsVersion</code>
+attribute, then it is assumed that the application requires only OpenGL ES 1.0,
+which is supported by all Android-powered devices.</p>
+
+ <p>An application can assume that if a platform supports a given OpenGL ES
+version, it also supports all numerically lower OpenGL ES versions. Therefore,
+an application that requires both OpenGL ES 1.0 and OpenGL ES 2.0 must specify
+that it requires OpenGL ES 2.0.</p>
+
+ <p>An application that can work with any of several OpenGL ES versions should
+only specify the numerically lowest version of OpenGL ES that it requires. (It
+can check at run-time whether a higher level of OpenGL ES is available.)</p>
</dd>
<dt><a name="name"></a>{@code android:name}</dt>
@@ -90,7 +131,7 @@
<table>
<tr>
<th>Feature</th>
- <th>Value</th>
+ <th>Attribute Value</th>
<th>Description</th>
</tr><tr>
<td rowspan="2">Camera</td>
@@ -130,6 +171,11 @@
<td>The application requires a device with a light sensor.
</td>
</tr><tr>
+ <td>Live Wallpaper</td>
+ <td>{@code android.software.live_wallpaper}</td>
+ <td>The application uses or provides Live Wallpapers and should be installed only on devices that support Live Wallpapers.
+ </td>
+ </tr><tr>
<td>Proximity sensor</td>
<td>{@code android.hardware.sensor.proximity}</td>
<td>The application requires a device with a proximity sensor.
diff --git a/docs/html/index.jd b/docs/html/index.jd
index e12a00a..e3bf685 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -13,7 +13,7 @@
<!-- total max width is 520px -->
<img src="/assets/images/home/Android_Dev_Lab_l.png" alt="Android developer labs" width="100px" style="padding-left:78px;padding-right:46px;padding-bottom: 8px;"/>
<div id="announcement" style="width:275px">
-<p>We're hosting the next Android Developer Lab in Barcelona at <a href="http://www.mobileworldcongress.com/index.htm">Mobile World Congress »</a> on Wednesday February 17th at <a href="http://www.mobileworldcongress.com/exhibition/app_planet.htm">App Planet »</a>, located in Hall 7. Come visit us to attend a technical presentation, talk to our Android developer relations team, and meet other members of the developer community.</p><p>Check the Android Developers blog for more information soon!</p>
+<p>We're hosting the next Android Developer Lab in Barcelona at <a href="http://www.mobileworldcongress.com/index.htm">Mobile World Congress »</a> on Wednesday February 17th at <a href="http://www.mobileworldcongress.com/exhibition/app_planet.htm">App Planet »</a>, located in Hall 7. Come visit us to attend a technical presentation, talk to our Android developer relations team, and meet other members of the developer community.</p><p><a href="http://sites.google.com/site/androidmwc/home">Learn more »</a></p>
<!--<p><a href="http://android-developers.blogspot.com/2009/11/bring-your-lab-coats.html">Learn more »</a></p>-->
</div> <!-- end annoucement -->
</div> <!-- end annoucement-block -->
diff --git a/docs/html/mwc2010/index.html b/docs/html/mwc2010/index.html
index 22319a2..c91386f 100644
--- a/docs/html/mwc2010/index.html
+++ b/docs/html/mwc2010/index.html
@@ -1,7 +1,7 @@
<html>
<head>
<title>Redirecting...</title>
-<meta http-equiv="refresh" content="0;url=/index.html">
+<meta http-equiv="refresh" content="0;url=http://sites.google.com/site/androidmwc/home">
</head>
<body>
</body>
diff --git a/docs/html/sdk/android-2.1.jd b/docs/html/sdk/android-2.1.jd
index ecdc366..b546f0f 100644
--- a/docs/html/sdk/android-2.1.jd
+++ b/docs/html/sdk/android-2.1.jd
@@ -218,6 +218,21 @@
<li>Updated {@link android.app.WallpaperManager}.</li>
</ul>
+<p>Additionally, if your application uses or provides Live Wallpapers, you must
+remember to add a <a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><code><uses-feature></code></a>
+ element to the application's manifest, declaring the attribute
+<code>android:name="android.software.live_wallpaper"</code>. For example:</p>
+
+<pre class="no-pretty-print">
+<uses-feature android:name="android.software.live_wallpaper" />
+</pre>
+
+<p>When you've published your application, Android Market checks for the
+presence of this element and uses it as a filter, ensuring that your application
+is not made available to users whose devices do not support Live Wallpapers.
+</p>
+
<h4>Telephony</h4>
<ul>
diff --git a/docs/html/search.jd b/docs/html/search.jd
index d0e7478..609ade9 100644
--- a/docs/html/search.jd
+++ b/docs/html/search.jd
@@ -2,7 +2,7 @@
@jd:body
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/jquery-history.js" type="text/javascript"></script>
+<script src="{@docRoot}assets/jquery-history.js" type="text/javascript"></script>
<script type="text/javascript">
var tabIndex = 0;
diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp
index 055dbca..096aa73 100644
--- a/libs/audioflinger/AudioPolicyManagerBase.cpp
+++ b/libs/audioflinger/AudioPolicyManagerBase.cpp
@@ -15,8 +15,7 @@
*/
#define LOG_TAG "AudioPolicyManagerBase"
-//
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <hardware_legacy/AudioPolicyManagerBase.h>
#include <media/mediarecorder.h>
diff --git a/mms-common/Android.mk b/mms-common/Android.mk
new file mode 100644
index 0000000..de994c0
--- /dev/null
+++ b/mms-common/Android.mk
@@ -0,0 +1,29 @@
+# Copyright (C) 2009 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# Note: the source code is in java/, not src/, because this code is also part of
+# the framework library, and build/core/pathmap.mk expects a java/ subdirectory.
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := mms-common
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Include this library in the build server's output directory
+$(call dist-for-goals, droid, $(LOCAL_BUILT_MODULE):mms-common.jar)
+
+# Build the test package
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/java/com/google/android/mms/pdu/CharacterSets.java b/mms-common/java/com/android/common/CharacterSets.java
similarity index 98%
rename from core/java/com/google/android/mms/pdu/CharacterSets.java
rename to mms-common/java/com/android/common/CharacterSets.java
index 4e22ca5..f19b078 100644
--- a/core/java/com/google/android/mms/pdu/CharacterSets.java
+++ b/mms-common/java/com/android/common/CharacterSets.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
diff --git a/core/java/com/google/android/mms/ContentType.java b/mms-common/java/com/android/common/ContentType.java
similarity index 98%
copy from core/java/com/google/android/mms/ContentType.java
copy to mms-common/java/com/android/common/ContentType.java
index 94bc9fd..ca449fe 100644
--- a/core/java/com/google/android/mms/ContentType.java
+++ b/mms-common/java/com/android/common/ContentType.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms;
+package com.android.mmscommon;
import java.util.ArrayList;
@@ -26,6 +26,7 @@
public static final String MMS_GENERIC = "application/vnd.wap.mms-generic";
public static final String MULTIPART_MIXED = "application/vnd.wap.multipart.mixed";
public static final String MULTIPART_RELATED = "application/vnd.wap.multipart.related";
+ public static final String MULTIPART_ALTERNATIVE = "application/vnd.wap.multipart.alternative";
public static final String TEXT_PLAIN = "text/plain";
public static final String TEXT_HTML = "text/html";
diff --git a/core/java/com/google/android/mms/pdu/EncodedStringValue.java b/mms-common/java/com/android/common/EncodedStringValue.java
similarity index 99%
rename from core/java/com/google/android/mms/pdu/EncodedStringValue.java
rename to mms-common/java/com/android/common/EncodedStringValue.java
index a27962d..0a4424e 100644
--- a/core/java/com/google/android/mms/pdu/EncodedStringValue.java
+++ b/mms-common/java/com/android/common/EncodedStringValue.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon;
import android.util.Config;
import android.util.Log;
@@ -269,7 +269,7 @@
return new EncodedStringValue(value.mCharacterSet, value.mData);
}
-
+
public static EncodedStringValue[] encodeStrings(String[] array) {
int count = array.length;
if (count > 0) {
diff --git a/core/java/com/google/android/mms/InvalidHeaderValueException.java b/mms-common/java/com/android/common/InvalidHeaderValueException.java
similarity index 97%
rename from core/java/com/google/android/mms/InvalidHeaderValueException.java
rename to mms-common/java/com/android/common/InvalidHeaderValueException.java
index 73d7832..34d5871 100644
--- a/core/java/com/google/android/mms/InvalidHeaderValueException.java
+++ b/mms-common/java/com/android/common/InvalidHeaderValueException.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms;
+package com.android.mmscommon;
/**
* Thrown when an invalid header value was set.
diff --git a/core/java/com/google/android/mms/MmsException.java b/mms-common/java/com/android/common/MmsException.java
similarity index 97%
rename from core/java/com/google/android/mms/MmsException.java
rename to mms-common/java/com/android/common/MmsException.java
index 6ca0c7e..296a2c3 100644
--- a/core/java/com/google/android/mms/MmsException.java
+++ b/mms-common/java/com/android/common/MmsException.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms;
+package com.android.mmscommon;
/**
* A generic exception that is thrown by the Mms client.
diff --git a/core/java/com/google/android/mms/pdu/PduHeaders.java b/mms-common/java/com/android/common/PduHeaders.java
similarity index 97%
rename from core/java/com/google/android/mms/pdu/PduHeaders.java
rename to mms-common/java/com/android/common/PduHeaders.java
index 4313815..d8f1211 100644
--- a/core/java/com/google/android/mms/pdu/PduHeaders.java
+++ b/mms-common/java/com/android/common/PduHeaders.java
@@ -15,9 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
+package com.android.mmscommon;
import java.util.ArrayList;
import java.util.HashMap;
@@ -339,7 +337,7 @@
* with specified header field. Return 0 if
* the value is not set.
*/
- protected int getOctet(int field) {
+ public int getOctet(int field) {
Integer octet = (Integer) mHeaderMap.get(field);
if (null == octet) {
return 0;
@@ -355,7 +353,7 @@
* @param field the field
* @throws InvalidHeaderValueException if the value is invalid.
*/
- protected void setOctet(int value, int field)
+ public void setOctet(int value, int field)
throws InvalidHeaderValueException{
/**
* Check whether this field can be set for specific
@@ -499,7 +497,7 @@
* @return the TextString value of the pdu header
* with specified header field
*/
- protected byte[] getTextString(int field) {
+ public byte[] getTextString(int field) {
return (byte[]) mHeaderMap.get(field);
}
@@ -512,7 +510,7 @@
* with specified header field
* @throws NullPointerException if the value is null.
*/
- protected void setTextString(byte[] value, int field) {
+ public void setTextString(byte[] value, int field) {
/**
* Check whether this field can be set for specific
* header and check validity of the field.
@@ -548,7 +546,7 @@
* @return the EncodedStringValue value of the pdu header
* with specified header field
*/
- protected EncodedStringValue getEncodedStringValue(int field) {
+ public EncodedStringValue getEncodedStringValue(int field) {
return (EncodedStringValue) mHeaderMap.get(field);
}
@@ -559,7 +557,7 @@
* @return the EncodeStringValue array of the pdu header
* with specified header field
*/
- protected EncodedStringValue[] getEncodedStringValues(int field) {
+ public EncodedStringValue[] getEncodedStringValues(int field) {
ArrayList<EncodedStringValue> list =
(ArrayList<EncodedStringValue>) mHeaderMap.get(field);
if (null == list) {
@@ -578,7 +576,7 @@
* with specified header field
* @throws NullPointerException if the value is null.
*/
- protected void setEncodedStringValue(EncodedStringValue value, int field) {
+ public void setEncodedStringValue(EncodedStringValue value, int field) {
/**
* Check whether this field can be set for specific
* header and check validity of the field.
@@ -615,7 +613,7 @@
* with specified header field
* @throws NullPointerException if the value is null.
*/
- protected void setEncodedStringValues(EncodedStringValue[] value, int field) {
+ public void setEncodedStringValues(EncodedStringValue[] value, int field) {
/**
* Check whether this field can be set for specific
* header and check validity of the field.
@@ -648,7 +646,7 @@
* @param field the field
* @throws NullPointerException if the value is null.
*/
- protected void appendEncodedStringValue(EncodedStringValue value,
+ public void appendEncodedStringValue(EncodedStringValue value,
int field) {
if (null == value) {
throw new NullPointerException();
@@ -680,7 +678,7 @@
* with specified header field. if return -1, the
* field is not existed in pdu header.
*/
- protected long getLongInteger(int field) {
+ public long getLongInteger(int field) {
Long longInteger = (Long) mHeaderMap.get(field);
if (null == longInteger) {
return -1;
@@ -695,7 +693,7 @@
* @param value the value
* @param field the field
*/
- protected void setLongInteger(long value, int field) {
+ public void setLongInteger(long value, int field) {
/**
* Check whether this field can be set for specific
* header and check validity of the field.
diff --git a/core/java/com/google/android/mms/ContentType.java b/mms-common/java/com/android/common/mms/ContentType.java
similarity index 98%
rename from core/java/com/google/android/mms/ContentType.java
rename to mms-common/java/com/android/common/mms/ContentType.java
index 94bc9fd..0fdb46c 100644
--- a/core/java/com/google/android/mms/ContentType.java
+++ b/mms-common/java/com/android/common/mms/ContentType.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms;
+package com.android.mms.mms;
import java.util.ArrayList;
@@ -26,6 +26,7 @@
public static final String MMS_GENERIC = "application/vnd.wap.mms-generic";
public static final String MULTIPART_MIXED = "application/vnd.wap.multipart.mixed";
public static final String MULTIPART_RELATED = "application/vnd.wap.multipart.related";
+ public static final String MULTIPART_ALTERNATIVE = "application/vnd.wap.multipart.alternative";
public static final String TEXT_PLAIN = "text/plain";
public static final String TEXT_HTML = "text/html";
diff --git a/core/java/com/google/android/mms/pdu/AcknowledgeInd.java b/mms-common/java/com/android/common/mms/pdu/AcknowledgeInd.java
similarity index 94%
rename from core/java/com/google/android/mms/pdu/AcknowledgeInd.java
rename to mms-common/java/com/android/common/mms/pdu/AcknowledgeInd.java
index 0e96c60..d1243b2 100644
--- a/core/java/com/google/android/mms/pdu/AcknowledgeInd.java
+++ b/mms-common/java/com/android/common/mms/pdu/AcknowledgeInd.java
@@ -15,9 +15,10 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
/**
* M-Acknowledge.ind PDU.
diff --git a/core/java/com/google/android/mms/pdu/Base64.java b/mms-common/java/com/android/common/mms/pdu/Base64.java
similarity index 98%
rename from core/java/com/google/android/mms/pdu/Base64.java
rename to mms-common/java/com/android/common/mms/pdu/Base64.java
index 604bee0..4c95dec 100644
--- a/core/java/com/google/android/mms/pdu/Base64.java
+++ b/mms-common/java/com/android/common/mms/pdu/Base64.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
public class Base64 {
/**
diff --git a/core/java/com/google/android/mms/pdu/DeliveryInd.java b/mms-common/java/com/android/common/mms/pdu/DeliveryInd.java
similarity index 94%
rename from core/java/com/google/android/mms/pdu/DeliveryInd.java
rename to mms-common/java/com/android/common/mms/pdu/DeliveryInd.java
index dafa8d1..e83729b 100644
--- a/core/java/com/google/android/mms/pdu/DeliveryInd.java
+++ b/mms-common/java/com/android/common/mms/pdu/DeliveryInd.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
/**
* M-Delivery.Ind Pdu.
diff --git a/core/java/com/google/android/mms/pdu/GenericPdu.java b/mms-common/java/com/android/common/mms/pdu/GenericPdu.java
similarity index 93%
rename from core/java/com/google/android/mms/pdu/GenericPdu.java
rename to mms-common/java/com/android/common/mms/pdu/GenericPdu.java
index 705de6a..c38e502 100644
--- a/core/java/com/google/android/mms/pdu/GenericPdu.java
+++ b/mms-common/java/com/android/common/mms/pdu/GenericPdu.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
public class GenericPdu {
/**
diff --git a/core/java/com/google/android/mms/pdu/MultimediaMessagePdu.java b/mms-common/java/com/android/common/mms/pdu/MultimediaMessagePdu.java
similarity index 94%
rename from core/java/com/google/android/mms/pdu/MultimediaMessagePdu.java
rename to mms-common/java/com/android/common/mms/pdu/MultimediaMessagePdu.java
index 5a85e0e..04fde2d 100644
--- a/core/java/com/google/android/mms/pdu/MultimediaMessagePdu.java
+++ b/mms-common/java/com/android/common/mms/pdu/MultimediaMessagePdu.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
/**
* Multimedia message PDU.
diff --git a/core/java/com/google/android/mms/pdu/NotificationInd.java b/mms-common/java/com/android/common/mms/pdu/NotificationInd.java
similarity index 97%
rename from core/java/com/google/android/mms/pdu/NotificationInd.java
rename to mms-common/java/com/android/common/mms/pdu/NotificationInd.java
index c56cba6..24f17b09 100644
--- a/core/java/com/google/android/mms/pdu/NotificationInd.java
+++ b/mms-common/java/com/android/common/mms/pdu/NotificationInd.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
/**
* M-Notification.ind PDU.
diff --git a/core/java/com/google/android/mms/pdu/NotifyRespInd.java b/mms-common/java/com/android/common/mms/pdu/NotifyRespInd.java
similarity index 95%
rename from core/java/com/google/android/mms/pdu/NotifyRespInd.java
rename to mms-common/java/com/android/common/mms/pdu/NotifyRespInd.java
index 2cc2fce..c2e2b26 100644
--- a/core/java/com/google/android/mms/pdu/NotifyRespInd.java
+++ b/mms-common/java/com/android/common/mms/pdu/NotifyRespInd.java
@@ -15,9 +15,10 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
/**
* M-NofifyResp.ind PDU.
diff --git a/core/java/com/google/android/mms/pdu/PduBody.java b/mms-common/java/com/android/common/mms/pdu/PduBody.java
similarity index 98%
rename from core/java/com/google/android/mms/pdu/PduBody.java
rename to mms-common/java/com/android/common/mms/pdu/PduBody.java
index fa0416c..cc28d80 100644
--- a/core/java/com/google/android/mms/pdu/PduBody.java
+++ b/mms-common/java/com/android/common/mms/pdu/PduBody.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
import java.util.HashMap;
import java.util.Map;
diff --git a/core/java/com/google/android/mms/pdu/PduComposer.java b/mms-common/java/com/android/common/mms/pdu/PduComposer.java
similarity index 99%
rename from core/java/com/google/android/mms/pdu/PduComposer.java
rename to mms-common/java/com/android/common/mms/pdu/PduComposer.java
index 8940945..bb3116d 100644
--- a/core/java/com/google/android/mms/pdu/PduComposer.java
+++ b/mms-common/java/com/android/common/mms/pdu/PduComposer.java
@@ -15,7 +15,10 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
+
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.PduHeaders;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/com/google/android/mms/pdu/PduContentTypes.java b/mms-common/java/com/android/common/mms/pdu/PduContentTypes.java
similarity index 98%
rename from core/java/com/google/android/mms/pdu/PduContentTypes.java
rename to mms-common/java/com/android/common/mms/pdu/PduContentTypes.java
index 7799e0e..3f971fd 100644
--- a/core/java/com/google/android/mms/pdu/PduContentTypes.java
+++ b/mms-common/java/com/android/common/mms/pdu/PduContentTypes.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
public class PduContentTypes {
/**
diff --git a/core/java/com/google/android/mms/pdu/PduParser.java b/mms-common/java/com/android/common/mms/pdu/PduParser.java
similarity index 98%
rename from core/java/com/google/android/mms/pdu/PduParser.java
rename to mms-common/java/com/android/common/mms/pdu/PduParser.java
index d465c5a..9253f83 100644
--- a/core/java/com/google/android/mms/pdu/PduParser.java
+++ b/mms-common/java/com/android/common/mms/pdu/PduParser.java
@@ -15,10 +15,13 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.ContentType;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.ContentType;
+import com.android.mmscommon.CharacterSets;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
import android.util.Config;
import android.util.Log;
@@ -157,9 +160,11 @@
}
String ctTypeStr = new String(contentType);
if (ctTypeStr.equals(ContentType.MULTIPART_MIXED)
- || ctTypeStr.equals(ContentType.MULTIPART_RELATED)) {
+ || ctTypeStr.equals(ContentType.MULTIPART_RELATED)
+ || ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
// The MMS content type must be "application/vnd.wap.multipart.mixed"
// or "application/vnd.wap.multipart.related"
+ // or "application/vnd.wap.multipart.alternative"
return retrieveConf;
}
return null;
diff --git a/core/java/com/google/android/mms/pdu/PduPart.java b/mms-common/java/com/android/common/mms/pdu/PduPart.java
similarity index 99%
rename from core/java/com/google/android/mms/pdu/PduPart.java
rename to mms-common/java/com/android/common/mms/pdu/PduPart.java
index b43e388..7d51b86 100644
--- a/core/java/com/google/android/mms/pdu/PduPart.java
+++ b/mms-common/java/com/android/common/mms/pdu/PduPart.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
import android.net.Uri;
diff --git a/core/java/com/google/android/mms/pdu/PduPersister.java b/mms-common/java/com/android/common/mms/pdu/PduPersister.java
similarity index 96%
rename from core/java/com/google/android/mms/pdu/PduPersister.java
rename to mms-common/java/com/android/common/mms/pdu/PduPersister.java
index 1f754bc..46f28c7 100644
--- a/core/java/com/google/android/mms/pdu/PduPersister.java
+++ b/mms-common/java/com/android/common/mms/pdu/PduPersister.java
@@ -15,14 +15,19 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.ContentType;
-import com.google.android.mms.InvalidHeaderValueException;
-import com.google.android.mms.MmsException;
-import com.google.android.mms.util.PduCache;
-import com.google.android.mms.util.PduCacheEntry;
-import com.google.android.mms.util.SqliteWrapper;
+import com.android.mmscommon.mms.pdu.PduPersister;
+
+import com.android.mmscommon.ContentType;
+import com.android.mmscommon.CharacterSets;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.MmsException;
+import com.android.mmscommon.PduHeaders;
+import com.android.mmscommon.mms.util.PduCache;
+import com.android.mmscommon.mms.util.PduCacheEntry;
+import android.database.sqlite.SqliteWrapper;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -31,13 +36,13 @@
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
-import android.provider.Telephony;
-import android.provider.Telephony.Mms;
-import android.provider.Telephony.MmsSms;
-import android.provider.Telephony.Threads;
-import android.provider.Telephony.Mms.Addr;
-import android.provider.Telephony.Mms.Part;
-import android.provider.Telephony.MmsSms.PendingMessages;
+import com.android.mmscommon.telephony.TelephonyProvider;
+import com.android.mmscommon.telephony.TelephonyProvider.Mms;
+import com.android.mmscommon.telephony.TelephonyProvider.MmsSms;
+import com.android.mmscommon.telephony.TelephonyProvider.Threads;
+import com.android.mmscommon.telephony.TelephonyProvider.Mms.Addr;
+import com.android.mmscommon.telephony.TelephonyProvider.Mms.Part;
+import com.android.mmscommon.telephony.TelephonyProvider.MmsSms.PendingMessages;
import android.text.TextUtils;
import android.util.Config;
import android.util.Log;
@@ -55,7 +60,6 @@
import java.util.Set;
import java.util.Map.Entry;
-import com.google.android.mms.pdu.EncodedStringValue;
/**
* This class is the high-level manager of PDU storage.
@@ -422,7 +426,8 @@
// Store simple string values directly in the database instead of an
// external file. This makes the text searchable and retrieval slightly
// faster.
- if ("text/plain".equals(type) || "application/smil".equals(type)) {
+ if (ContentType.TEXT_PLAIN.equals(type) || ContentType.APP_SMIL.equals(type)
+ || ContentType.TEXT_HTML.equals(type)) {
String text = c.getString(PART_COLUMN_TEXT);
if (text == null) {
text = "";
@@ -738,9 +743,11 @@
try {
byte[] data = part.getData();
- if ("text/plain".equals(contentType) || "application/smil".equals(contentType)) {
+ if (ContentType.TEXT_PLAIN.equals(contentType)
+ || ContentType.APP_SMIL.equals(contentType)
+ || ContentType.TEXT_HTML.equals(contentType)) {
ContentValues cv = new ContentValues();
- cv.put(Telephony.Mms.Part.TEXT, new EncodedStringValue(data).getString());
+ cv.put(TelephonyProvider.Mms.Part.TEXT, new EncodedStringValue(data).getString());
if (mContentResolver.update(uri, cv, null, null) != 1) {
throw new MmsException("unable to update " + uri.toString());
}
diff --git a/core/java/com/google/android/mms/pdu/QuotedPrintable.java b/mms-common/java/com/android/common/mms/pdu/QuotedPrintable.java
similarity index 97%
rename from core/java/com/google/android/mms/pdu/QuotedPrintable.java
rename to mms-common/java/com/android/common/mms/pdu/QuotedPrintable.java
index a34ed12..e9da7df 100644
--- a/core/java/com/google/android/mms/pdu/QuotedPrintable.java
+++ b/mms-common/java/com/android/common/mms/pdu/QuotedPrintable.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
import java.io.ByteArrayOutputStream;
diff --git a/core/java/com/google/android/mms/pdu/ReadOrigInd.java b/mms-common/java/com/android/common/mms/pdu/ReadOrigInd.java
similarity index 95%
rename from core/java/com/google/android/mms/pdu/ReadOrigInd.java
rename to mms-common/java/com/android/common/mms/pdu/ReadOrigInd.java
index 1bfc0bb..9678784 100644
--- a/core/java/com/google/android/mms/pdu/ReadOrigInd.java
+++ b/mms-common/java/com/android/common/mms/pdu/ReadOrigInd.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
public class ReadOrigInd extends GenericPdu {
/**
diff --git a/core/java/com/google/android/mms/pdu/ReadRecInd.java b/mms-common/java/com/android/common/mms/pdu/ReadRecInd.java
similarity index 95%
rename from core/java/com/google/android/mms/pdu/ReadRecInd.java
rename to mms-common/java/com/android/common/mms/pdu/ReadRecInd.java
index 880e3ac..c1efbbc 100644
--- a/core/java/com/google/android/mms/pdu/ReadRecInd.java
+++ b/mms-common/java/com/android/common/mms/pdu/ReadRecInd.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
public class ReadRecInd extends GenericPdu {
/**
diff --git a/core/java/com/google/android/mms/pdu/RetrieveConf.java b/mms-common/java/com/android/common/mms/pdu/RetrieveConf.java
similarity index 97%
rename from core/java/com/google/android/mms/pdu/RetrieveConf.java
rename to mms-common/java/com/android/common/mms/pdu/RetrieveConf.java
index 98e67c0..442949e 100644
--- a/core/java/com/google/android/mms/pdu/RetrieveConf.java
+++ b/mms-common/java/com/android/common/mms/pdu/RetrieveConf.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
/**
* M-Retrive.conf Pdu.
diff --git a/core/java/com/google/android/mms/pdu/SendConf.java b/mms-common/java/com/android/common/mms/pdu/SendConf.java
similarity index 94%
rename from core/java/com/google/android/mms/pdu/SendConf.java
rename to mms-common/java/com/android/common/mms/pdu/SendConf.java
index 0568fe79..0a57b6b 100644
--- a/core/java/com/google/android/mms/pdu/SendConf.java
+++ b/mms-common/java/com/android/common/mms/pdu/SendConf.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
public class SendConf extends GenericPdu {
/**
diff --git a/core/java/com/google/android/mms/pdu/SendReq.java b/mms-common/java/com/android/common/mms/pdu/SendReq.java
similarity index 97%
rename from core/java/com/google/android/mms/pdu/SendReq.java
rename to mms-common/java/com/android/common/mms/pdu/SendReq.java
index 597cd00..5da4719 100644
--- a/core/java/com/google/android/mms/pdu/SendReq.java
+++ b/mms-common/java/com/android/common/mms/pdu/SendReq.java
@@ -15,11 +15,13 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
import android.util.Log;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
public class SendReq extends MultimediaMessagePdu {
private static final String TAG = "SendReq";
diff --git a/mms-common/java/com/android/common/mms/telephony/TelephonyProvider.java b/mms-common/java/com/android/common/mms/telephony/TelephonyProvider.java
new file mode 100644
index 0000000..0237bc2
--- /dev/null
+++ b/mms-common/java/com/android/common/mms/telephony/TelephonyProvider.java
@@ -0,0 +1,1790 @@
+/*
+ * Copyright (C) 2006 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.mmscommon.telephony;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.BaseColumns;
+import android.telephony.SmsMessage;
+import android.text.TextUtils;
+import android.util.Config;
+import android.util.Log;
+
+import com.android.common.Patterns;
+import android.database.sqlite.SqliteWrapper;
+
+/**
+ * The Telephony provider contains data related to phone operation.
+ *
+ * @hide
+ */
+
+// This is a copy of the private TelephoneProvider.java file found in:
+// com.android.providers.telephony
+// TODO: keep these files in sync.
+
+public final class TelephonyProvider {
+ private static final String TAG = "Telephony";
+ private static final boolean DEBUG = true;
+ private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
+
+// public static final Pattern EMAIL_ADDRESS
+// = Pattern.compile(
+// "[a-zA-Z0-9\\+\\.\\_\\%\\-]{1,256}" +
+// "\\@" +
+// "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" +
+// "(" +
+// "\\." +
+// "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" +
+// ")+"
+// );
+//
+// /**
+// * This pattern is intended for searching for things that look like they
+// * might be phone numbers in arbitrary text, not for validating whether
+// * something is in fact a phone number. It will miss many things that
+// * are legitimate phone numbers.
+// *
+// * <p> The pattern matches the following:
+// * <ul>
+// * <li>Optionally, a + sign followed immediately by one or more digits. Spaces, dots, or dashes
+// * may follow.
+// * <li>Optionally, sets of digits in parentheses, separated by spaces, dots, or dashes.
+// * <li>A string starting and ending with a digit, containing digits, spaces, dots, and/or dashes.
+// * </ul>
+// */
+// public static final Pattern PHONE
+// = Pattern.compile( // sdd = space, dot, or dash
+// "(\\+[0-9]+[\\- \\.]*)?" // +<digits><sdd>*
+// + "(\\([0-9]+\\)[\\- \\.]*)?" // (<digits>)<sdd>*
+// + "([0-9][0-9\\- \\.][0-9\\- \\.]+[0-9])"); // <digit><digit|sdd>+<digit>
+
+ // Constructor
+ public TelephonyProvider() {
+ }
+
+ /**
+ * Base columns for tables that contain text based SMSs.
+ */
+ public interface TextBasedSmsColumns {
+ /**
+ * The type of the message
+ * <P>Type: INTEGER</P>
+ */
+ public static final String TYPE = "type";
+
+ public static final int MESSAGE_TYPE_ALL = 0;
+ public static final int MESSAGE_TYPE_INBOX = 1;
+ public static final int MESSAGE_TYPE_SENT = 2;
+ public static final int MESSAGE_TYPE_DRAFT = 3;
+ public static final int MESSAGE_TYPE_OUTBOX = 4;
+ public static final int MESSAGE_TYPE_FAILED = 5; // for failed outgoing messages
+ public static final int MESSAGE_TYPE_QUEUED = 6; // for messages to send later
+
+
+ /**
+ * The thread ID of the message
+ * <P>Type: INTEGER</P>
+ */
+ public static final String THREAD_ID = "thread_id";
+
+ /**
+ * The address of the other party
+ * <P>Type: TEXT</P>
+ */
+ public static final String ADDRESS = "address";
+
+ /**
+ * The person ID of the sender
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String PERSON_ID = "person";
+
+ /**
+ * The date the message was sent
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DATE = "date";
+
+ /**
+ * Has the message been read
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String READ = "read";
+
+ /**
+ * The TP-Status value for the message, or -1 if no status has
+ * been received
+ */
+ public static final String STATUS = "status";
+
+ public static final int STATUS_NONE = -1;
+ public static final int STATUS_COMPLETE = 0;
+ public static final int STATUS_PENDING = 64;
+ public static final int STATUS_FAILED = 128;
+
+ /**
+ * The subject of the message, if present
+ * <P>Type: TEXT</P>
+ */
+ public static final String SUBJECT = "subject";
+
+ /**
+ * The body of the message
+ * <P>Type: TEXT</P>
+ */
+ public static final String BODY = "body";
+
+ /**
+ * The id of the sender of the conversation, if present
+ * <P>Type: INTEGER (reference to item in content://contacts/people)</P>
+ */
+ public static final String PERSON = "person";
+
+ /**
+ * The protocol identifier code
+ * <P>Type: INTEGER</P>
+ */
+ public static final String PROTOCOL = "protocol";
+
+ /**
+ * Whether the <code>TP-Reply-Path</code> bit was set on this message
+ * <P>Type: BOOLEAN</P>
+ */
+ public static final String REPLY_PATH_PRESENT = "reply_path_present";
+
+ /**
+ * The service center (SC) through which to send the message, if present
+ * <P>Type: TEXT</P>
+ */
+ public static final String SERVICE_CENTER = "service_center";
+
+ /**
+ * Has the message been locked?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String LOCKED = "locked";
+
+ /**
+ * Error code associated with sending or receiving this message
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR_CODE = "error_code";
+}
+
+ /**
+ * Contains all text based SMS messages.
+ */
+ public static final class Sms implements BaseColumns, TextBasedSmsColumns {
+ public static final Cursor query(ContentResolver cr, String[] projection) {
+ return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
+ }
+
+ public static final Cursor query(ContentResolver cr, String[] projection,
+ String where, String orderBy) {
+ return cr.query(CONTENT_URI, projection, where,
+ null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
+ }
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://sms");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the given URI.
+ *
+ * @param resolver the content resolver to use
+ * @param uri the URI to add the message to
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param read true if the message has been read, false if not
+ * @param deliveryReport true if a delivery report was requested, false if not
+ * @return the URI for the new message
+ */
+ public static Uri addMessageToUri(ContentResolver resolver,
+ Uri uri, String address, String body, String subject,
+ Long date, boolean read, boolean deliveryReport) {
+ return addMessageToUri(resolver, uri, address, body, subject,
+ date, read, deliveryReport, -1L);
+ }
+
+ /**
+ * Add an SMS to the given URI with thread_id specified.
+ *
+ * @param resolver the content resolver to use
+ * @param uri the URI to add the message to
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param read true if the message has been read, false if not
+ * @param deliveryReport true if a delivery report was requested, false if not
+ * @param threadId the thread_id of the message
+ * @return the URI for the new message
+ */
+ public static Uri addMessageToUri(ContentResolver resolver,
+ Uri uri, String address, String body, String subject,
+ Long date, boolean read, boolean deliveryReport, long threadId) {
+ ContentValues values = new ContentValues(7);
+
+ values.put(ADDRESS, address);
+ if (date != null) {
+ values.put(DATE, date);
+ }
+ values.put(READ, read ? Integer.valueOf(1) : Integer.valueOf(0));
+ values.put(SUBJECT, subject);
+ values.put(BODY, body);
+ if (deliveryReport) {
+ values.put(STATUS, STATUS_PENDING);
+ }
+ if (threadId != -1L) {
+ values.put(THREAD_ID, threadId);
+ }
+ return resolver.insert(uri, values);
+ }
+
+ /**
+ * Move a message to the given folder.
+ *
+ * @param context the context to use
+ * @param uri the message to move
+ * @param folder the folder to move to
+ * @return true if the operation succeeded
+ */
+ public static boolean moveMessageToFolder(Context context,
+ Uri uri, int folder, int error) {
+ if (uri == null) {
+ return false;
+ }
+
+ boolean markAsUnread = false;
+ boolean markAsRead = false;
+ switch(folder) {
+ case MESSAGE_TYPE_INBOX:
+ case MESSAGE_TYPE_DRAFT:
+ break;
+ case MESSAGE_TYPE_OUTBOX:
+ case MESSAGE_TYPE_SENT:
+ markAsRead = true;
+ break;
+ case MESSAGE_TYPE_FAILED:
+ case MESSAGE_TYPE_QUEUED:
+ markAsUnread = true;
+ break;
+ default:
+ return false;
+ }
+
+ ContentValues values = new ContentValues(3);
+
+ values.put(TYPE, folder);
+ if (markAsUnread) {
+ values.put(READ, Integer.valueOf(0));
+ } else if (markAsRead) {
+ values.put(READ, Integer.valueOf(1));
+ }
+ values.put(ERROR_CODE, error);
+
+ return 1 == SqliteWrapper.update(context, context.getContentResolver(),
+ uri, values, null, null);
+ }
+
+ /**
+ * Returns true iff the folder (message type) identifies an
+ * outgoing message.
+ */
+ public static boolean isOutgoingFolder(int messageType) {
+ return (messageType == MESSAGE_TYPE_FAILED)
+ || (messageType == MESSAGE_TYPE_OUTBOX)
+ || (messageType == MESSAGE_TYPE_SENT)
+ || (messageType == MESSAGE_TYPE_QUEUED);
+ }
+
+ /**
+ * Contains all text based SMS messages in the SMS app's inbox.
+ */
+ public static final class Inbox implements BaseColumns, TextBasedSmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://sms/inbox");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the Draft box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param read true if the message has been read, false if not
+ * @return the URI for the new message
+ */
+ public static Uri addMessage(ContentResolver resolver,
+ String address, String body, String subject, Long date,
+ boolean read) {
+ return addMessageToUri(resolver, CONTENT_URI, address, body,
+ subject, date, read, false);
+ }
+ }
+
+ /**
+ * Contains all sent text based SMS messages in the SMS app's.
+ */
+ public static final class Sent implements BaseColumns, TextBasedSmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://sms/sent");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the Draft box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @return the URI for the new message
+ */
+ public static Uri addMessage(ContentResolver resolver,
+ String address, String body, String subject, Long date) {
+ return addMessageToUri(resolver, CONTENT_URI, address, body,
+ subject, date, true, false);
+ }
+ }
+
+ /**
+ * Contains all sent text based SMS messages in the SMS app's.
+ */
+ public static final class Draft implements BaseColumns, TextBasedSmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://sms/draft");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the Draft box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @return the URI for the new message
+ */
+ public static Uri addMessage(ContentResolver resolver,
+ String address, String body, String subject, Long date) {
+ return addMessageToUri(resolver, CONTENT_URI, address, body,
+ subject, date, true, false);
+ }
+
+ /**
+ * Save over an existing draft message.
+ *
+ * @param resolver the content resolver to use
+ * @param uri of existing message
+ * @param body the new body for the draft message
+ * @return true is successful, false otherwise
+ */
+ public static boolean saveMessage(ContentResolver resolver,
+ Uri uri, String body) {
+ ContentValues values = new ContentValues(2);
+ values.put(BODY, body);
+ values.put(DATE, System.currentTimeMillis());
+ return resolver.update(uri, values, null, null) == 1;
+ }
+ }
+
+ /**
+ * Contains all pending outgoing text based SMS messages.
+ */
+ public static final class Outbox implements BaseColumns, TextBasedSmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://sms/outbox");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the Out box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param deliveryReport whether a delivery report was requested for the message
+ * @return the URI for the new message
+ */
+ public static Uri addMessage(ContentResolver resolver,
+ String address, String body, String subject, Long date,
+ boolean deliveryReport, long threadId) {
+ return addMessageToUri(resolver, CONTENT_URI, address, body,
+ subject, date, true, deliveryReport, threadId);
+ }
+ }
+
+ /**
+ * Contains all sent text-based SMS messages in the SMS app's.
+ */
+ public static final class Conversations
+ implements BaseColumns, TextBasedSmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://sms/conversations");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * The first 45 characters of the body of the message
+ * <P>Type: TEXT</P>
+ */
+ public static final String SNIPPET = "snippet";
+
+ /**
+ * The number of messages in the conversation
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_COUNT = "msg_count";
+ }
+
+ /**
+ * Contains info about SMS related Intents that are broadcast.
+ */
+ public static final class Intents {
+ /**
+ * Set by BroadcastReceiver. Indicates the message was handled
+ * successfully.
+ */
+ public static final int RESULT_SMS_HANDLED = 1;
+
+ /**
+ * Set by BroadcastReceiver. Indicates a generic error while
+ * processing the message.
+ */
+ public static final int RESULT_SMS_GENERIC_ERROR = 2;
+
+ /**
+ * Set by BroadcastReceiver. Indicates insufficient memory to store
+ * the message.
+ */
+ public static final int RESULT_SMS_OUT_OF_MEMORY = 3;
+
+ /**
+ * Set by BroadcastReceiver. Indicates the message, while
+ * possibly valid, is of a format or encoding that is not
+ * supported.
+ */
+ public static final int RESULT_SMS_UNSUPPORTED = 4;
+
+ /**
+ * Broadcast Action: A new text based SMS message has been received
+ * by the device. The intent will have the following extra
+ * values:</p>
+ *
+ * <ul>
+ * <li><em>pdus</em> - An Object[] od byte[]s containing the PDUs
+ * that make up the message.</li>
+ * </ul>
+ *
+ * <p>The extra values can be extracted using
+ * {@link #getMessagesFromIntent(Intent)}.</p>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ */
+ public static final String SMS_RECEIVED_ACTION =
+ "android.provider.Telephony.SMS_RECEIVED";
+
+ /**
+ * Broadcast Action: A new data based SMS message has been received
+ * by the device. The intent will have the following extra
+ * values:</p>
+ *
+ * <ul>
+ * <li><em>pdus</em> - An Object[] od byte[]s containing the PDUs
+ * that make up the message.</li>
+ * </ul>
+ *
+ * <p>The extra values can be extracted using
+ * {@link #getMessagesFromIntent(Intent)}.</p>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ */
+ public static final String DATA_SMS_RECEIVED_ACTION =
+ "android.intent.action.DATA_SMS_RECEIVED";
+
+ /**
+ * Broadcast Action: A new WAP PUSH message has been received by the
+ * device. The intent will have the following extra
+ * values:</p>
+ *
+ * <ul>
+ * <li><em>transactionId (Integer)</em> - The WAP transaction
+ * ID</li>
+ * <li><em>pduType (Integer)</em> - The WAP PDU type</li>
+ * <li><em>header (byte[])</em> - The header of the message</li>
+ * <li><em>data (byte[])</em> - The data payload of the message</li>
+ * </ul>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ */
+ public static final String WAP_PUSH_RECEIVED_ACTION =
+ "android.provider.Telephony.WAP_PUSH_RECEIVED";
+
+ /**
+ * Broadcast Action: The SIM storage for SMS messages is full. If
+ * space is not freed, messages targeted for the SIM (class 2) may
+ * not be saved.
+ */
+ public static final String SIM_FULL_ACTION =
+ "android.provider.Telephony.SIM_FULL";
+
+ /**
+ * Broadcast Action: An incoming SMS has been rejected by the
+ * telephony framework. This intent is sent in lieu of any
+ * of the RECEIVED_ACTION intents. The intent will have the
+ * following extra value:</p>
+ *
+ * <ul>
+ * <li><em>result</em> - An int result code, eg,
+ * <code>{@link #RESULT_SMS_OUT_OF_MEMORY}</code>,
+ * indicating the error returned to the network.</li>
+ * </ul>
+
+ */
+ public static final String SMS_REJECTED_ACTION =
+ "android.provider.Telephony.SMS_REJECTED";
+
+ /**
+ * Broadcast Action: The phone service state has changed. The intent will have the following
+ * extra values:</p>
+ * <ul>
+ * <li><em>state</em> - An int with one of the following values:
+ * {@link android.telephony.ServiceState#STATE_IN_SERVICE},
+ * {@link android.telephony.ServiceState#STATE_OUT_OF_SERVICE},
+ * {@link android.telephony.ServiceState#STATE_EMERGENCY_ONLY}
+ * or {@link android.telephony.ServiceState#STATE_POWER_OFF}
+ * <li><em>roaming</em> - A boolean value indicating whether the phone is roaming.</li>
+ * <li><em>operator-alpha-long</em> - The carrier name as a string.</li>
+ * <li><em>operator-alpha-short</em> - A potentially shortened version of the carrier name,
+ * as a string.</li>
+ * <li><em>operator-numeric</em> - A number representing the carrier, as a string. This is
+ * a five or six digit number consisting of the MCC (Mobile Country Code, 3 digits)
+ * and MNC (Mobile Network code, 2-3 digits).</li>
+ * <li><em>manual</em> - A boolean, where true indicates that the user has chosen to select
+ * the network manually, and false indicates that network selection is handled by the
+ * phone.</li>
+ * </ul>
+ *
+ * <p class="note">
+ * Requires the READ_PHONE_STATE permission.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ */
+ public static final String ACTION_SERVICE_STATE_CHANGED =
+ "android.intent.action.SERVICE_STATE";
+
+ /**
+ * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a
+ * {@link #DATA_SMS_RECEIVED_ACTION} intent.
+ *
+ * @param intent the intent to read from
+ * @return an array of SmsMessages for the PDUs
+ */
+ public static final SmsMessage[] getMessagesFromIntent(
+ Intent intent) {
+ Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
+ byte[][] pduObjs = new byte[messages.length][];
+
+ for (int i = 0; i < messages.length; i++) {
+ pduObjs[i] = (byte[]) messages[i];
+ }
+ byte[][] pdus = new byte[pduObjs.length][];
+ int pduCount = pdus.length;
+ SmsMessage[] msgs = new SmsMessage[pduCount];
+ for (int i = 0; i < pduCount; i++) {
+ pdus[i] = pduObjs[i];
+ msgs[i] = SmsMessage.createFromPdu(pdus[i]);
+ }
+ return msgs;
+ }
+ }
+ }
+
+ /**
+ * Base columns for tables that contain MMSs.
+ */
+ public interface BaseMmsColumns extends BaseColumns {
+
+ public static final int MESSAGE_BOX_ALL = 0;
+ public static final int MESSAGE_BOX_INBOX = 1;
+ public static final int MESSAGE_BOX_SENT = 2;
+ public static final int MESSAGE_BOX_DRAFTS = 3;
+ public static final int MESSAGE_BOX_OUTBOX = 4;
+
+ /**
+ * The date the message was sent.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DATE = "date";
+
+ /**
+ * The box which the message belong to, for example, MESSAGE_BOX_INBOX.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_BOX = "msg_box";
+
+ /**
+ * Has the message been read.
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String READ = "read";
+
+ /**
+ * The Message-ID of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MESSAGE_ID = "m_id";
+
+ /**
+ * The subject of the message, if present.
+ * <P>Type: TEXT</P>
+ */
+ public static final String SUBJECT = "sub";
+
+ /**
+ * The character set of the subject, if present.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SUBJECT_CHARSET = "sub_cs";
+
+ /**
+ * The Content-Type of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CONTENT_TYPE = "ct_t";
+
+ /**
+ * The Content-Location of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CONTENT_LOCATION = "ct_l";
+
+ /**
+ * The address of the sender.
+ * <P>Type: TEXT</P>
+ */
+ public static final String FROM = "from";
+
+ /**
+ * The address of the recipients.
+ * <P>Type: TEXT</P>
+ */
+ public static final String TO = "to";
+
+ /**
+ * The address of the cc. recipients.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CC = "cc";
+
+ /**
+ * The address of the bcc. recipients.
+ * <P>Type: TEXT</P>
+ */
+ public static final String BCC = "bcc";
+
+ /**
+ * The expiry time of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String EXPIRY = "exp";
+
+ /**
+ * The class of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MESSAGE_CLASS = "m_cls";
+
+ /**
+ * The type of the message defined by MMS spec.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_TYPE = "m_type";
+
+ /**
+ * The version of specification that this message conform.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MMS_VERSION = "v";
+
+ /**
+ * The size of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_SIZE = "m_size";
+
+ /**
+ * The priority of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PRIORITY = "pri";
+
+ /**
+ * The read-report of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String READ_REPORT = "rr";
+
+ /**
+ * Whether the report is allowed.
+ * <P>Type: TEXT</P>
+ */
+ public static final String REPORT_ALLOWED = "rpt_a";
+
+ /**
+ * The response-status of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String RESPONSE_STATUS = "resp_st";
+
+ /**
+ * The status of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String STATUS = "st";
+
+ /**
+ * The transaction-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String TRANSACTION_ID = "tr_id";
+
+ /**
+ * The retrieve-status of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String RETRIEVE_STATUS = "retr_st";
+
+ /**
+ * The retrieve-text of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RETRIEVE_TEXT = "retr_txt";
+
+ /**
+ * The character set of the retrieve-text.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RETRIEVE_TEXT_CHARSET = "retr_txt_cs";
+
+ /**
+ * The read-status of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String READ_STATUS = "read_status";
+
+ /**
+ * The content-class of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CONTENT_CLASS = "ct_cls";
+
+ /**
+ * The delivery-report of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String DELIVERY_REPORT = "d_rpt";
+
+ /**
+ * The delivery-time-token of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String DELIVERY_TIME_TOKEN = "d_tm_tok";
+
+ /**
+ * The delivery-time of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String DELIVERY_TIME = "d_tm";
+
+ /**
+ * The response-text of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RESPONSE_TEXT = "resp_txt";
+
+ /**
+ * The sender-visibility of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String SENDER_VISIBILITY = "s_vis";
+
+ /**
+ * The reply-charging of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String REPLY_CHARGING = "r_chg";
+
+ /**
+ * The reply-charging-deadline-token of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String REPLY_CHARGING_DEADLINE_TOKEN = "r_chg_dl_tok";
+
+ /**
+ * The reply-charging-deadline of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String REPLY_CHARGING_DEADLINE = "r_chg_dl";
+
+ /**
+ * The reply-charging-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String REPLY_CHARGING_ID = "r_chg_id";
+
+ /**
+ * The reply-charging-size of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String REPLY_CHARGING_SIZE = "r_chg_sz";
+
+ /**
+ * The previously-sent-by of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PREVIOUSLY_SENT_BY = "p_s_by";
+
+ /**
+ * The previously-sent-date of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String PREVIOUSLY_SENT_DATE = "p_s_d";
+
+ /**
+ * The store of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String STORE = "store";
+
+ /**
+ * The mm-state of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MM_STATE = "mm_st";
+
+ /**
+ * The mm-flags-token of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MM_FLAGS_TOKEN = "mm_flg_tok";
+
+ /**
+ * The mm-flags of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MM_FLAGS = "mm_flg";
+
+ /**
+ * The store-status of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String STORE_STATUS = "store_st";
+
+ /**
+ * The store-status-text of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String STORE_STATUS_TEXT = "store_st_txt";
+
+ /**
+ * The stored of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String STORED = "stored";
+
+ /**
+ * The totals of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String TOTALS = "totals";
+
+ /**
+ * The mbox-totals of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MBOX_TOTALS = "mb_t";
+
+ /**
+ * The mbox-totals-token of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MBOX_TOTALS_TOKEN = "mb_t_tok";
+
+ /**
+ * The quotas of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String QUOTAS = "qt";
+
+ /**
+ * The mbox-quotas of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MBOX_QUOTAS = "mb_qt";
+
+ /**
+ * The mbox-quotas-token of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MBOX_QUOTAS_TOKEN = "mb_qt_tok";
+
+ /**
+ * The message-count of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_COUNT = "m_cnt";
+
+ /**
+ * The start of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String START = "start";
+
+ /**
+ * The distribution-indicator of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String DISTRIBUTION_INDICATOR = "d_ind";
+
+ /**
+ * The element-descriptor of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String ELEMENT_DESCRIPTOR = "e_des";
+
+ /**
+ * The limit of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String LIMIT = "limit";
+
+ /**
+ * The recommended-retrieval-mode of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String RECOMMENDED_RETRIEVAL_MODE = "r_r_mod";
+
+ /**
+ * The recommended-retrieval-mode-text of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RECOMMENDED_RETRIEVAL_MODE_TEXT = "r_r_mod_txt";
+
+ /**
+ * The status-text of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String STATUS_TEXT = "st_txt";
+
+ /**
+ * The applic-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String APPLIC_ID = "apl_id";
+
+ /**
+ * The reply-applic-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String REPLY_APPLIC_ID = "r_apl_id";
+
+ /**
+ * The aux-applic-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String AUX_APPLIC_ID = "aux_apl_id";
+
+ /**
+ * The drm-content of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String DRM_CONTENT = "drm_c";
+
+ /**
+ * The adaptation-allowed of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String ADAPTATION_ALLOWED = "adp_a";
+
+ /**
+ * The replace-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String REPLACE_ID = "repl_id";
+
+ /**
+ * The cancel-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CANCEL_ID = "cl_id";
+
+ /**
+ * The cancel-status of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CANCEL_STATUS = "cl_st";
+
+ /**
+ * The thread ID of the message
+ * <P>Type: INTEGER</P>
+ */
+ public static final String THREAD_ID = "thread_id";
+
+ /**
+ * Has the message been locked?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String LOCKED = "locked";
+ }
+
+ /**
+ * Columns for the "canonical_addresses" table used by MMS and
+ * SMS."
+ */
+ public interface CanonicalAddressesColumns extends BaseColumns {
+ /**
+ * An address used in MMS or SMS. Email addresses are
+ * converted to lower case and are compared by string
+ * equality. Other addresses are compared using
+ * PHONE_NUMBERS_EQUAL.
+ * <P>Type: TEXT</P>
+ */
+ public static final String ADDRESS = "address";
+ }
+
+ /**
+ * Columns for the "threads" table used by MMS and SMS.
+ */
+ public interface ThreadsColumns extends BaseColumns {
+ /**
+ * The date at which the thread was created.
+ *
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DATE = "date";
+
+ /**
+ * A string encoding of the recipient IDs of the recipients of
+ * the message, in numerical order and separated by spaces.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RECIPIENT_IDS = "recipient_ids";
+
+ /**
+ * The message count of the thread.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_COUNT = "message_count";
+ /**
+ * Indicates whether all messages of the thread have been read.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String READ = "read";
+ /**
+ * The snippet of the latest message in the thread.
+ * <P>Type: TEXT</P>
+ */
+ public static final String SNIPPET = "snippet";
+ /**
+ * The charset of the snippet.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SNIPPET_CHARSET = "snippet_cs";
+ /**
+ * Type of the thread, either Threads.COMMON_THREAD or
+ * Threads.BROADCAST_THREAD.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String TYPE = "type";
+ /**
+ * Indicates whether there is a transmission error in the thread.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR = "error";
+ /**
+ * Indicates whether this thread contains any attachments.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String HAS_ATTACHMENT = "has_attachment";
+ }
+
+ /**
+ * Helper functions for the "threads" table used by MMS and SMS.
+ */
+ public static final class Threads implements ThreadsColumns {
+ private static final String[] ID_PROJECTION = { BaseColumns._ID };
+ private static final String STANDARD_ENCODING = "UTF-8";
+ private static final Uri THREAD_ID_CONTENT_URI = Uri.parse(
+ "content://mms-sms/threadID");
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(
+ MmsSms.CONTENT_URI, "conversations");
+ public static final Uri OBSOLETE_THREADS_URI = Uri.withAppendedPath(
+ CONTENT_URI, "obsolete");
+
+ public static final int COMMON_THREAD = 0;
+ public static final int BROADCAST_THREAD = 1;
+
+ // No one should construct an instance of this class.
+ private Threads() {
+ }
+
+ /**
+ * This is a single-recipient version of
+ * getOrCreateThreadId. It's convenient for use with SMS
+ * messages.
+ */
+ public static long getOrCreateThreadId(Context context, String recipient) {
+ Set<String> recipients = new HashSet<String>();
+
+ recipients.add(recipient);
+ return getOrCreateThreadId(context, recipients);
+ }
+
+ /**
+ * Given the recipients list and subject of an unsaved message,
+ * return its thread ID. If the message starts a new thread,
+ * allocate a new thread ID. Otherwise, use the appropriate
+ * existing thread ID.
+ *
+ * Find the thread ID of the same set of recipients (in
+ * any order, without any additions). If one
+ * is found, return it. Otherwise, return a unique thread ID.
+ */
+ public static long getOrCreateThreadId(
+ Context context, Set<String> recipients) {
+ Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon();
+
+ for (String recipient : recipients) {
+ if (Mms.isEmailAddress(recipient)) {
+ recipient = Mms.extractAddrSpec(recipient);
+ }
+
+ uriBuilder.appendQueryParameter("recipient", recipient);
+ }
+
+ Uri uri = uriBuilder.build();
+ if (DEBUG) {
+ Log.v(TAG, "getOrCreateThreadId uri: " + uri);
+ }
+ Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
+ uri, ID_PROJECTION, null, null, null);
+ if (DEBUG) {
+ Log.v(TAG, "getOrCreateThreadId cursor cnt: " + cursor.getCount());
+ }
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ return cursor.getLong(0);
+ } else {
+ Log.e(TAG, "getOrCreateThreadId returned no rows!");
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+
+ Log.e(TAG, "getOrCreateThreadId failed with uri " + uri.toString());
+ throw new IllegalArgumentException("Unable to find or allocate a thread ID.");
+ }
+ }
+
+ /**
+ * Contains all MMS messages.
+ */
+ public static final class Mms implements BaseMmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://mms");
+
+ public static final Uri REPORT_REQUEST_URI = Uri.withAppendedPath(
+ CONTENT_URI, "report-request");
+
+ public static final Uri REPORT_STATUS_URI = Uri.withAppendedPath(
+ CONTENT_URI, "report-status");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * mailbox = name-addr
+ * name-addr = [display-name] angle-addr
+ * angle-addr = [CFWS] "<" addr-spec ">" [CFWS]
+ */
+ public static final Pattern NAME_ADDR_EMAIL_PATTERN =
+ Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
+
+ /**
+ * quoted-string = [CFWS]
+ * DQUOTE *([FWS] qcontent) [FWS] DQUOTE
+ * [CFWS]
+ */
+ public static final Pattern QUOTED_STRING_PATTERN =
+ Pattern.compile("\\s*\"([^\"]*)\"\\s*");
+
+ public static final Cursor query(
+ ContentResolver cr, String[] projection) {
+ return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
+ }
+
+ public static final Cursor query(
+ ContentResolver cr, String[] projection,
+ String where, String orderBy) {
+ return cr.query(CONTENT_URI, projection,
+ where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
+ }
+
+ public static final String getMessageBoxName(int msgBox) {
+ switch (msgBox) {
+ case MESSAGE_BOX_ALL:
+ return "all";
+ case MESSAGE_BOX_INBOX:
+ return "inbox";
+ case MESSAGE_BOX_SENT:
+ return "sent";
+ case MESSAGE_BOX_DRAFTS:
+ return "drafts";
+ case MESSAGE_BOX_OUTBOX:
+ return "outbox";
+ default:
+ throw new IllegalArgumentException("Invalid message box: " + msgBox);
+ }
+ }
+
+ public static String extractAddrSpec(String address) {
+ Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address);
+
+ if (match.matches()) {
+ return match.group(2);
+ }
+ return address;
+ }
+
+ /**
+ * Returns true if the address is an email address
+ *
+ * @param address the input address to be tested
+ * @return true if address is an email address
+ */
+ public static boolean isEmailAddress(String address) {
+ if (TextUtils.isEmpty(address)) {
+ return false;
+ }
+
+ String s = extractAddrSpec(address);
+ Matcher match = Patterns.EMAIL_ADDRESS.matcher(s);
+ return match.matches();
+ }
+
+ /**
+ * Returns true if the number is a Phone number
+ *
+ * @param number the input number to be tested
+ * @return true if number is a Phone number
+ */
+ public static boolean isPhoneNumber(String number) {
+ if (TextUtils.isEmpty(number)) {
+ return false;
+ }
+
+ Matcher match = Patterns.PHONE.matcher(number);
+ return match.matches();
+ }
+
+ /**
+ * Contains all MMS messages in the MMS app's inbox.
+ */
+ public static final class Inbox implements BaseMmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri
+ CONTENT_URI = Uri.parse("content://mms/inbox");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ /**
+ * Contains all MMS messages in the MMS app's sent box.
+ */
+ public static final class Sent implements BaseMmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri
+ CONTENT_URI = Uri.parse("content://mms/sent");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ /**
+ * Contains all MMS messages in the MMS app's drafts box.
+ */
+ public static final class Draft implements BaseMmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri
+ CONTENT_URI = Uri.parse("content://mms/drafts");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ /**
+ * Contains all MMS messages in the MMS app's outbox.
+ */
+ public static final class Outbox implements BaseMmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri
+ CONTENT_URI = Uri.parse("content://mms/outbox");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ public static final class Addr implements BaseColumns {
+ /**
+ * The ID of MM which this address entry belongs to.
+ */
+ public static final String MSG_ID = "msg_id";
+
+ /**
+ * The ID of contact entry in Phone Book.
+ */
+ public static final String CONTACT_ID = "contact_id";
+
+ /**
+ * The address text.
+ */
+ public static final String ADDRESS = "address";
+
+ /**
+ * Type of address, must be one of PduHeaders.BCC,
+ * PduHeaders.CC, PduHeaders.FROM, PduHeaders.TO.
+ */
+ public static final String TYPE = "type";
+
+ /**
+ * Character set of this entry.
+ */
+ public static final String CHARSET = "charset";
+ }
+
+ public static final class Part implements BaseColumns {
+ /**
+ * The identifier of the message which this part belongs to.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MSG_ID = "mid";
+
+ /**
+ * The order of the part.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SEQ = "seq";
+
+ /**
+ * The content type of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CONTENT_TYPE = "ct";
+
+ /**
+ * The name of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String NAME = "name";
+
+ /**
+ * The charset of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CHARSET = "chset";
+
+ /**
+ * The file name of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String FILENAME = "fn";
+
+ /**
+ * The content disposition of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CONTENT_DISPOSITION = "cd";
+
+ /**
+ * The content ID of the part.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CONTENT_ID = "cid";
+
+ /**
+ * The content location of the part.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CONTENT_LOCATION = "cl";
+
+ /**
+ * The start of content-type of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CT_START = "ctt_s";
+
+ /**
+ * The type of content-type of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CT_TYPE = "ctt_t";
+
+ /**
+ * The location(on filesystem) of the binary data of the part.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String _DATA = "_data";
+
+ public static final String TEXT = "text";
+
+ }
+
+ public static final class Rate {
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(
+ Mms.CONTENT_URI, "rate");
+ /**
+ * When a message was successfully sent.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SENT_TIME = "sent_time";
+ }
+
+ public static final class ScrapSpace {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://mms/scrapSpace");
+
+ /**
+ * This is the scrap file we use to store the media attachment when the user
+ * chooses to capture a photo to be attached . We pass {#link@Uri} to the Camera app,
+ * which streams the captured image to the uri. Internally we write the media content
+ * to this file. It's named '.temp.jpg' so Gallery won't pick it up.
+ */
+ public static final String SCRAP_FILE_PATH = "/sdcard/mms/scrapSpace/.temp.jpg";
+ }
+
+ public static final class Intents {
+ private Intents() {
+ // Non-instantiatable.
+ }
+
+ /**
+ * The extra field to store the contents of the Intent,
+ * which should be an array of Uri.
+ */
+ public static final String EXTRA_CONTENTS = "contents";
+ /**
+ * The extra field to store the type of the contents,
+ * which should be an array of String.
+ */
+ public static final String EXTRA_TYPES = "types";
+ /**
+ * The extra field to store the 'Cc' addresses.
+ */
+ public static final String EXTRA_CC = "cc";
+ /**
+ * The extra field to store the 'Bcc' addresses;
+ */
+ public static final String EXTRA_BCC = "bcc";
+ /**
+ * The extra field to store the 'Subject'.
+ */
+ public static final String EXTRA_SUBJECT = "subject";
+ /**
+ * Indicates that the contents of specified URIs were changed.
+ * The application which is showing or caching these contents
+ * should be updated.
+ */
+ public static final String
+ CONTENT_CHANGED_ACTION = "android.intent.action.CONTENT_CHANGED";
+ /**
+ * An extra field which stores the URI of deleted contents.
+ */
+ public static final String DELETED_CONTENTS = "deleted_contents";
+ }
+ }
+
+ /**
+ * Contains all MMS and SMS messages.
+ */
+ public static final class MmsSms implements BaseColumns {
+ /**
+ * The column to distinguish SMS & MMS messages in query results.
+ */
+ public static final String TYPE_DISCRIMINATOR_COLUMN =
+ "transport_type";
+
+ public static final Uri CONTENT_URI = Uri.parse("content://mms-sms/");
+
+ public static final Uri CONTENT_CONVERSATIONS_URI = Uri.parse(
+ "content://mms-sms/conversations");
+
+ public static final Uri CONTENT_FILTER_BYPHONE_URI = Uri.parse(
+ "content://mms-sms/messages/byphone");
+
+ public static final Uri CONTENT_UNDELIVERED_URI = Uri.parse(
+ "content://mms-sms/undelivered");
+
+ public static final Uri CONTENT_DRAFT_URI = Uri.parse(
+ "content://mms-sms/draft");
+
+ public static final Uri CONTENT_LOCKED_URI = Uri.parse(
+ "content://mms-sms/locked");
+
+ /***
+ * Pass in a query parameter called "pattern" which is the text
+ * to search for.
+ * The sort order is fixed to be thread_id ASC,date DESC.
+ */
+ public static final Uri SEARCH_URI = Uri.parse(
+ "content://mms-sms/search");
+
+ // Constants for message protocol types.
+ public static final int SMS_PROTO = 0;
+ public static final int MMS_PROTO = 1;
+
+ // Constants for error types of pending messages.
+ public static final int NO_ERROR = 0;
+ public static final int ERR_TYPE_GENERIC = 1;
+ public static final int ERR_TYPE_SMS_PROTO_TRANSIENT = 2;
+ public static final int ERR_TYPE_MMS_PROTO_TRANSIENT = 3;
+ public static final int ERR_TYPE_TRANSPORT_FAILURE = 4;
+ public static final int ERR_TYPE_GENERIC_PERMANENT = 10;
+ public static final int ERR_TYPE_SMS_PROTO_PERMANENT = 11;
+ public static final int ERR_TYPE_MMS_PROTO_PERMANENT = 12;
+
+ public static final class PendingMessages implements BaseColumns {
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(
+ MmsSms.CONTENT_URI, "pending");
+ /**
+ * The type of transport protocol(MMS or SMS).
+ * <P>Type: INTEGER</P>
+ */
+ public static final String PROTO_TYPE = "proto_type";
+ /**
+ * The ID of the message to be sent or downloaded.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MSG_ID = "msg_id";
+ /**
+ * The type of the message to be sent or downloaded.
+ * This field is only valid for MM. For SM, its value is always
+ * set to 0.
+ */
+ public static final String MSG_TYPE = "msg_type";
+ /**
+ * The type of the error code.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR_TYPE = "err_type";
+ /**
+ * The error code of sending/retrieving process.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR_CODE = "err_code";
+ /**
+ * How many times we tried to send or download the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String RETRY_INDEX = "retry_index";
+ /**
+ * The time to do next retry.
+ */
+ public static final String DUE_TIME = "due_time";
+ /**
+ * The time we last tried to send or download the message.
+ */
+ public static final String LAST_TRY = "last_try";
+ }
+ }
+
+ public static final class Carriers implements BaseColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://telephony/carriers");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "name ASC";
+
+ public static final String NAME = "name";
+
+ public static final String APN = "apn";
+
+ public static final String PROXY = "proxy";
+
+ public static final String PORT = "port";
+
+ public static final String MMSPROXY = "mmsproxy";
+
+ public static final String MMSPORT = "mmsport";
+
+ public static final String SERVER = "server";
+
+ public static final String USER = "user";
+
+ public static final String PASSWORD = "password";
+
+ public static final String MMSC = "mmsc";
+
+ public static final String MCC = "mcc";
+
+ public static final String MNC = "mnc";
+
+ public static final String NUMERIC = "numeric";
+
+ public static final String AUTH_TYPE = "authtype";
+
+ public static final String TYPE = "type";
+
+ public static final String CURRENT = "current";
+ }
+
+ public static final class Intents {
+ private Intents() {
+ // Not instantiable
+ }
+
+ /**
+ * Broadcast Action: A "secret code" has been entered in the dialer. Secret codes are
+ * of the form *#*#<code>#*#*. The intent will have the data URI:</p>
+ *
+ * <p><code>android_secret_code://<code></code></p>
+ */
+ public static final String SECRET_CODE_ACTION =
+ "android.provider.Telephony.SECRET_CODE";
+
+ /**
+ * Broadcast Action: The Service Provider string(s) have been updated. Activities or
+ * services that use these strings should update their display.
+ * The intent will have the following extra values:</p>
+ * <ul>
+ * <li><em>showPlmn</em> - Boolean that indicates whether the PLMN should be shown.</li>
+ * <li><em>plmn</em> - The operator name of the registered network, as a string.</li>
+ * <li><em>showSpn</em> - Boolean that indicates whether the SPN should be shown.</li>
+ * <li><em>spn</em> - The service provider name, as a string.</li>
+ * </ul>
+ * Note that <em>showPlmn</em> may indicate that <em>plmn</em> should be displayed, even
+ * though the value for <em>plmn</em> is null. This can happen, for example, if the phone
+ * has not registered to a network yet. In this case the receiver may substitute an
+ * appropriate placeholder string (eg, "No service").
+ *
+ * It is recommended to display <em>plmn</em> before / above <em>spn</em> if
+ * both are displayed.
+ *
+ * <p>Note this is a protected intent that can only be sent
+ * by the system.
+ */
+ public static final String SPN_STRINGS_UPDATED_ACTION =
+ "android.provider.Telephony.SPN_STRINGS_UPDATED";
+
+ public static final String EXTRA_SHOW_PLMN = "showPlmn";
+ public static final String EXTRA_PLMN = "plmn";
+ public static final String EXTRA_SHOW_SPN = "showSpn";
+ public static final String EXTRA_SPN = "spn";
+ }
+}
diff --git a/core/java/com/google/android/mms/util/AbstractCache.java b/mms-common/java/com/android/common/mms/util/AbstractCache.java
similarity index 98%
rename from core/java/com/google/android/mms/util/AbstractCache.java
rename to mms-common/java/com/android/common/mms/util/AbstractCache.java
index 670439c..10a6fce 100644
--- a/core/java/com/google/android/mms/util/AbstractCache.java
+++ b/mms-common/java/com/android/common/mms/util/AbstractCache.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.util;
+package com.android.mmscommon.mms.util;
import android.util.Config;
import android.util.Log;
diff --git a/core/java/com/google/android/mms/util/PduCache.java b/mms-common/java/com/android/common/mms/util/PduCache.java
similarity index 98%
rename from core/java/com/google/android/mms/util/PduCache.java
rename to mms-common/java/com/android/common/mms/util/PduCache.java
index 7c3fad7..ca5432f 100644
--- a/core/java/com/google/android/mms/util/PduCache.java
+++ b/mms-common/java/com/android/common/mms/util/PduCache.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package com.google.android.mms.util;
+package com.android.mmscommon.mms.util;
import android.content.ContentUris;
import android.content.UriMatcher;
import android.net.Uri;
-import android.provider.Telephony.Mms;
+import com.android.mmscommon.telephony.TelephonyProvider.Mms;
import android.util.Config;
import android.util.Log;
diff --git a/core/java/com/google/android/mms/util/PduCacheEntry.java b/mms-common/java/com/android/common/mms/util/PduCacheEntry.java
similarity index 92%
rename from core/java/com/google/android/mms/util/PduCacheEntry.java
rename to mms-common/java/com/android/common/mms/util/PduCacheEntry.java
index 8b41386..aed741d 100644
--- a/core/java/com/google/android/mms/util/PduCacheEntry.java
+++ b/mms-common/java/com/android/common/mms/util/PduCacheEntry.java
@@ -15,9 +15,9 @@
* limitations under the License.
*/
-package com.google.android.mms.util;
+package com.android.mmscommon.mms.util;
-import com.google.android.mms.pdu.GenericPdu;
+import com.android.mmscommon.mms.pdu.GenericPdu;
public final class PduCacheEntry {
private final GenericPdu mPdu;
diff --git a/preloaded-classes b/preloaded-classes
index d108883..0c84904 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -686,10 +686,6 @@
com.google.android.gles_jni.EGLDisplayImpl
com.google.android.gles_jni.EGLImpl
com.google.android.gles_jni.GLImpl
-com.google.android.mms.ContentType
-com.google.android.mms.pdu.CharacterSets
-com.google.android.mms.pdu.PduPart
-com.google.android.mms.pdu.PduPersister
com.ibm.icu4jni.charset.CharsetDecoderICU
com.ibm.icu4jni.charset.CharsetEncoderICU
com.ibm.icu4jni.charset.CharsetICU
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 4417d7b..aa4956f 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -828,12 +828,15 @@
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);
+ NetworkStateTracker newNet = null;
+ if (mNetAttributes[prevNetType].isDefault()) {
+ 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();
@@ -848,7 +851,7 @@
}
}
- // returns -1 if no failover available
+ // returns null if no failover available
private NetworkStateTracker tryFailover(int prevNetType) {
/*
* If this is a default network, check if other defaults are available
@@ -970,13 +973,17 @@
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);
+ NetworkStateTracker newNet = null;
+ if (mNetAttributes[info.getType()].isDefault()) {
+ 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();
@@ -1280,9 +1287,16 @@
info = (NetworkInfo) msg.obj;
int type = info.getType();
NetworkInfo.State state = info.getState();
- if (mNetAttributes[type].mLastState == state) {
+ // only do this optimization for wifi. It going into scan mode for location
+ // services generates alot of noise. Meanwhile the mms apn won't send out
+ // subsequent notifications when on default cellular because it never
+ // disconnects.. so only do this to wifi notifications. Fixed better when the
+ // APN notifications are standardized.
+ if (mNetAttributes[type].mLastState == state &&
+ mNetAttributes[type].mRadio == ConnectivityManager.TYPE_WIFI) {
if (DBG) {
- // TODO - remove this after we validate the dropping doesn't break anything
+ // TODO - remove this after we validate the dropping doesn't break
+ // anything
Log.d(TAG, "Dropping ConnectivityChange for " +
info.getTypeName() + ": " +
state + "/" + info.getDetailedState());
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 7b8645f..17a3ab8 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -41,8 +41,10 @@
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.util.Log;
import android.util.Xml;
+import android.view.WindowManagerPolicy;
import java.io.File;
import java.io.FileInputStream;
@@ -161,30 +163,35 @@
return null;
}
- ActiveAdmin getActiveAdminForCallerLocked(ComponentName who)
- throws SecurityException {
- ActiveAdmin admin = mAdminMap.get(who);
- if (admin != null && admin.getUid() == Binder.getCallingUid()) {
- if (who != null) {
- if (!who.getPackageName().equals(admin.info.getActivityInfo().packageName)
- || !who.getClassName().equals(admin.info.getActivityInfo().name)) {
- throw new SecurityException("Current admin is not " + who);
- }
- }
- return admin;
- }
- throw new SecurityException("Current admin is not owned by uid " + Binder.getCallingUid());
- }
-
ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
throws SecurityException {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who);
- if (!admin.info.usesPolicy(reqPolicy)) {
- throw new SecurityException("Admin " + admin.info.getComponent()
- + " did not specify uses-policy for: "
- + admin.info.getTagForPolicy(reqPolicy));
+ final int callingUid = Binder.getCallingUid();
+ if (who != null) {
+ ActiveAdmin admin = mAdminMap.get(who);
+ if (admin == null) {
+ throw new SecurityException("No active admin " + who);
+ }
+ if (admin.getUid() != callingUid) {
+ throw new SecurityException("Admin " + who + " is not owned by uid "
+ + Binder.getCallingUid());
+ }
+ if (!admin.info.usesPolicy(reqPolicy)) {
+ throw new SecurityException("Admin " + admin.info.getComponent()
+ + " did not specify uses-policy for: "
+ + admin.info.getTagForPolicy(reqPolicy));
+ }
+ return admin;
+ } else {
+ final int N = mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = mAdminList.get(i);
+ if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
+ return admin;
+ }
+ }
+ throw new SecurityException("No active admin owned by uid "
+ + Binder.getCallingUid() + " for policy #" + reqPolicy);
}
- return admin;
}
void sendAdminCommandLocked(ActiveAdmin admin, String action) {
@@ -346,7 +353,7 @@
// Ignore
}
- long timeMs = getMaximumTimeToLock();
+ long timeMs = getMaximumTimeToLock(null);
if (timeMs <= 0) {
timeMs = Integer.MAX_VALUE;
}
@@ -355,7 +362,6 @@
} catch (RemoteException e) {
Log.w(TAG, "Failure talking with power manager", e);
}
-
}
public void systemReady() {
@@ -443,10 +449,16 @@
}
}
- public int getPasswordMode() {
+ public int getPasswordMode(ComponentName who) {
synchronized (this) {
- final int N = mAdminList.size();
int mode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+
+ if (who != null) {
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ return admin != null ? admin.passwordMode : mode;
+ }
+
+ final int N = mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = mAdminList.get(i);
if (mode < admin.passwordMode) {
@@ -457,7 +469,7 @@
}
}
- public void setMinimumPasswordLength(ComponentName who, int length) {
+ public void setPasswordMinimumLength(ComponentName who, int length) {
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -471,10 +483,16 @@
}
}
- public int getMinimumPasswordLength() {
+ public int getPasswordMinimumLength(ComponentName who) {
synchronized (this) {
- final int N = mAdminList.size();
int length = 0;
+
+ if (who != null) {
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ return admin != null ? admin.minimumPasswordLength : length;
+ }
+
+ final int N = mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = mAdminList.get(i);
if (length < admin.minimumPasswordLength) {
@@ -491,8 +509,8 @@
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
- return mActivePasswordMode >= getPasswordMode()
- && mActivePasswordLength >= getMinimumPasswordLength();
+ return mActivePasswordMode >= getPasswordMode(null)
+ && mActivePasswordLength >= getPasswordMinimumLength(null);
}
}
@@ -521,10 +539,16 @@
}
}
- public int getMaximumFailedPasswordsForWipe() {
+ public int getMaximumFailedPasswordsForWipe(ComponentName who) {
synchronized (this) {
- final int N = mAdminList.size();
int count = 0;
+
+ if (who != null) {
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ return admin != null ? admin.maximumFailedPasswordsForWipe : count;
+ }
+
+ final int N = mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = mAdminList.get(i);
if (count == 0) {
@@ -545,8 +569,8 @@
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
- mode = getPasswordMode();
- if (password.length() < getMinimumPasswordLength()) {
+ mode = getPasswordMode(null);
+ if (password.length() < getPasswordMinimumLength(null)) {
return false;
}
}
@@ -577,9 +601,12 @@
long ident = Binder.clearCallingIdentity();
try {
saveSettingsLocked();
+
+ timeMs = getMaximumTimeToLock(null);
if (timeMs <= 0) {
timeMs = Integer.MAX_VALUE;
}
+
try {
getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
} catch (RemoteException e) {
@@ -592,10 +619,16 @@
}
}
- public long getMaximumTimeToLock() {
+ public long getMaximumTimeToLock(ComponentName who) {
synchronized (this) {
- final int N = mAdminList.size();
long time = 0;
+
+ if (who != null) {
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ return admin != null ? admin.maximumTimeToUnlock : time;
+ }
+
+ final int N = mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = mAdminList.get(i);
if (time == 0) {
@@ -615,7 +648,14 @@
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
- // STOPSHIP need to implement.
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
+ WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
+ } catch (RemoteException e) {
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
}
@@ -702,7 +742,7 @@
try {
mFailedPasswordAttempts++;
saveSettingsLocked();
- int max = getMaximumFailedPasswordsForWipe();
+ int max = getMaximumFailedPasswordsForWipe(null);
if (max > 0 && mFailedPasswordAttempts >= max) {
wipeDataLocked(0);
}
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 9a1f8a6..05cea46 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -206,7 +206,7 @@
if (mUmsEnabled) {
if (newUmsNotifyEnabled) {
Intent intent = new Intent();
- intent.setClass(mContext, com.android.internal.app.UsbStorageStopActivity.class);
+ intent.setClass(mContext, com.android.internal.app.UsbStorageActivity.class);
PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
setUsbStorageNotification(com.android.internal.R.string.usb_storage_stop_notification_title,
com.android.internal.R.string.usb_storage_stop_notification_message,
@@ -866,7 +866,7 @@
if (mUmsActiveNotify) {
Intent intent = new Intent();
- intent.setClass(mContext, com.android.internal.app.UsbStorageStopActivity.class);
+ intent.setClass(mContext, com.android.internal.app.UsbStorageActivity.class);
PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
setUsbStorageNotification(com.android.internal.R.string.usb_storage_stop_notification_title,
com.android.internal.R.string.usb_storage_stop_notification_message,
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 3ffb8bf..cd4ae4cc 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4369,18 +4369,13 @@
String idxStr = "";
int idx = 1;
if (oldCodePath != null) {
- int eidx = -1;
- if (suffix != null) {
- eidx = oldCodePath.indexOf(suffix);
+ String subStr = oldCodePath;
+ if (subStr.startsWith(prefix)) {
+ subStr = subStr.substring(prefix.length());
}
- if (eidx == -1) {
- eidx = oldCodePath.length();
+ if (subStr.endsWith(suffix)) {
+ subStr = subStr.substring(0, subStr.length() - suffix.length());
}
- int sidx = oldCodePath.indexOf(prefix);
- if (sidx == -1) {
- sidx = 0;
- }
- String subStr = oldCodePath.substring(sidx + prefix.length(), eidx);
if (subStr != null) {
if (subStr.startsWith("-")) {
subStr = subStr.substring(1);
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index f106fc3..cefd312 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -1101,11 +1101,10 @@
// 0 was to turn it off, and we can't strip that, because keyguard needs to come
// on, so have to run the queue then.
if (index == 2) {
- // Also, while we're collapsing them, if it's going to be an "off," and one
- // is off because of user, then use that, regardless of whether it's the first
- // or second one.
- if (!on && why == WindowManagerPolicy.OFF_BECAUSE_OF_USER) {
- mBroadcastWhy[0] = WindowManagerPolicy.OFF_BECAUSE_OF_USER;
+ // While we're collapsing them, if it's going off, and the new reason
+ // is more significant than the first, then use the new one.
+ if (!on && mBroadcastWhy[0] > why) {
+ mBroadcastWhy[0] = why;
}
mBroadcastQueue[0] = on ? 1 : 0;
mBroadcastQueue[1] = -1;
@@ -2136,9 +2135,18 @@
*/
public void goToSleep(long time)
{
+ goToSleepWithReason(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
+ }
+
+ /**
+ * The user requested that we go to sleep (probably with the power button).
+ * This overrides all wake locks that are held.
+ */
+ public void goToSleepWithReason(long time, int reason)
+ {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
synchronized (mLocks) {
- goToSleepLocked(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
+ goToSleepLocked(time, reason);
}
}
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index d5de1f0..7951fb7 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -923,7 +923,7 @@
String value = field.value();
if (value != null) {
if (field != config.eap) {
- value = convertToQuotedString(value);
+ value = (value.length() == 0) ? "NULL" : convertToQuotedString(value);
}
if (!WifiNative.setNetworkVariableCommand(
netId,
diff --git a/services/java/com/android/server/WifiWatchdogService.java b/services/java/com/android/server/WifiWatchdogService.java
index 9443a95..f2347ed 100644
--- a/services/java/com/android/server/WifiWatchdogService.java
+++ b/services/java/com/android/server/WifiWatchdogService.java
@@ -739,6 +739,8 @@
// Black list this "bad" AP, this will cause an attempt to connect to another
blacklistAp(ap.bssid);
+ // Initiate an association to an alternate AP
+ mWifiStateTracker.reassociate();
}
private void blacklistAp(String bssid) {
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index 1e322bd..0928d2b 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -119,6 +119,26 @@
private final WifiStateTracker mWifiStateTracker;
+ /**
+ * This indicates the supplicant connection for the monitor is closed
+ */
+ private static final String monitorSocketClosed = "connection closed";
+
+ /**
+ * This indicates a read error on the monitor socket conenction
+ */
+ private static final String wpaRecvError = "recv error";
+
+ /**
+ * Tracks consecutive receive errors
+ */
+ private int mRecvErrors = 0;
+
+ /**
+ * Max errors before we close supplicant connection
+ */
+ private static final int MAX_RECV_ERRORS = 10;
+
public WifiMonitor(WifiStateTracker tracker) {
mWifiStateTracker = tracker;
}
@@ -151,16 +171,13 @@
for (;;) {
String eventStr = WifiNative.waitForEvent();
- if (eventStr == null) {
- continue;
- }
-
// Skip logging the common but mostly uninteresting scan-results event
if (Config.LOGD && eventStr.indexOf(scanResultsEvent) == -1) {
Log.v(TAG, "Event [" + eventStr + "]");
}
if (!eventStr.startsWith(eventPrefix)) {
- if (eventStr.startsWith(wpaEventPrefix) && 0 < eventStr.indexOf(passwordKeyMayBeIncorrectEvent)) {
+ if (eventStr.startsWith(wpaEventPrefix) &&
+ 0 < eventStr.indexOf(passwordKeyMayBeIncorrectEvent)) {
handlePasswordKeyMayBeIncorrect();
}
continue;
@@ -216,12 +233,38 @@
} else if (event == DRIVER_STATE) {
handleDriverEvent(eventData);
} else if (event == TERMINATING) {
+ /**
+ * If monitor socket is closed, we have already
+ * stopped the supplicant, simply exit the monitor thread
+ */
+ if (eventData.startsWith(monitorSocketClosed)) {
+ if (Config.LOGD) {
+ Log.d(TAG, "Monitor socket is closed, exiting thread");
+ }
+ break;
+ }
+
+ /**
+ * Close the supplicant connection if we see
+ * too many recv errors
+ */
+ if (eventData.startsWith(wpaRecvError)) {
+ if (++mRecvErrors > MAX_RECV_ERRORS) {
+ if (Config.LOGD) {
+ Log.d(TAG, "too many recv errors, closing connection");
+ }
+ } else {
+ continue;
+ }
+ }
+
+ // notify and exit
mWifiStateTracker.notifySupplicantLost();
- // If supplicant is gone, exit the thread
break;
} else {
handleEvent(event, eventData);
}
+ mRecvErrors = 0;
}
}
@@ -293,6 +336,7 @@
private void handleSupplicantStateChange(String dataString) {
String[] dataTokens = dataString.split(" ");
+ String BSSID = null;
int networkId = -1;
int newState = -1;
for (String token : dataTokens) {
@@ -301,6 +345,11 @@
continue;
}
+ if (nameValue[0].equals("BSSID")) {
+ BSSID = nameValue[1];
+ continue;
+ }
+
int value;
try {
value = Integer.parseInt(nameValue[1]);
@@ -328,7 +377,7 @@
if (newSupplicantState == SupplicantState.INVALID) {
Log.w(TAG, "Invalid supplicant state: " + newState);
}
- mWifiStateTracker.notifyStateChange(networkId, newSupplicantState);
+ mWifiStateTracker.notifyStateChange(networkId, BSSID, newSupplicantState);
}
}
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 2668fe0..cb615d2 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -304,11 +304,13 @@
* thread.
*/
private static class SupplicantStateChangeResult {
- SupplicantStateChangeResult(int networkId, SupplicantState state) {
+ SupplicantStateChangeResult(int networkId, String BSSID, SupplicantState state) {
this.state = state;
+ this.BSSID = BSSID;
this.networkId = networkId;
}
int networkId;
+ String BSSID;
SupplicantState state;
}
@@ -512,10 +514,10 @@
* @param networkId the configured network on which the state change occurred
* @param newState the new {@code SupplicantState}
*/
- void notifyStateChange(int networkId, SupplicantState newState) {
+ void notifyStateChange(int networkId, String BSSID, SupplicantState newState) {
Message msg = Message.obtain(
this, EVENT_SUPPLICANT_STATE_CHANGED,
- new SupplicantStateChangeResult(networkId, newState));
+ new SupplicantStateChangeResult(networkId, BSSID, newState));
msg.sendToTarget();
}
@@ -884,6 +886,13 @@
int networkId = supplicantStateResult.networkId;
+ /**
+ * The SupplicantState BSSID value is valid in ASSOCIATING state only.
+ * The NetworkState BSSID value comes upon a successful connection.
+ */
+ if (supplicantStateResult.state == SupplicantState.ASSOCIATING) {
+ mLastBssid = supplicantStateResult.BSSID;
+ }
/*
* If we get disconnect or inactive we need to start our
* watchdog timer to start a scan
@@ -928,6 +937,7 @@
setSupplicantState(newState);
if (newState == SupplicantState.DORMANT) {
DetailedState newDetailedState;
+ Message reconnectMsg = obtainMessage(EVENT_DEFERRED_RECONNECT, mLastBssid);
if (mIsScanOnly || mRunState == RUN_STATE_STOPPING) {
newDetailedState = DetailedState.IDLE;
} else {
@@ -942,7 +952,7 @@
* milliseconds.
*/
if (mRunState == RUN_STATE_RUNNING && !mIsScanOnly && networkId != -1) {
- sendEmptyMessageDelayed(EVENT_DEFERRED_RECONNECT, RECONNECT_DELAY_MSECS);
+ sendMessageDelayed(reconnectMsg, RECONNECT_DELAY_MSECS);
} else if (mRunState == RUN_STATE_STOPPING) {
synchronized (this) {
WifiNative.stopDriverCommand();
@@ -1104,15 +1114,19 @@
break;
case EVENT_DEFERRED_RECONNECT:
- /*
+ String BSSID = msg.obj.toString();
+ /**
* If we've exceeded the maximum number of retries for reconnecting
- * to a given network, disable the network so that the supplicant
- * will try some other network, if any is available.
- * TODO: network ID may have changed since we stored it.
+ * to a given network, blacklist the BSSID to allow a connection attempt on
+ * an alternate BSSID if available
*/
if (mWifiInfo.getSupplicantState() != SupplicantState.UNINITIALIZED) {
if (++mReconnectCount > getMaxDhcpRetries()) {
- mWM.disableNetwork(mLastNetworkId);
+ if (LOCAL_LOGD) {
+ Log.d(TAG, "Failed reconnect count: " +
+ mReconnectCount + " Blacklisting " + BSSID);
+ }
+ addToBlacklist(BSSID);
}
synchronized(this) {
WifiNative.reconnectCommand();
@@ -1684,6 +1698,10 @@
mNumScansSinceNetworkStateChange = 0;
}
+ public synchronized boolean reassociate() {
+ return WifiNative.reassociateCommand();
+ }
+
public synchronized boolean addToBlacklist(String bssid) {
return WifiNative.addToBlacklistCommand(bssid);
}