Merge "Tag stagefright development tools as "debug-only"."
diff --git a/api/current.xml b/api/current.xml
index 2729ff4..67c5dc2 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -211739,6 +211739,17 @@
<parameter name="measureSpec" type="int">
</parameter>
</method>
+<method name="resume"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="seekTo"
return="void"
abstract="false"
@@ -211852,6 +211863,17 @@
visibility="public"
>
</method>
+<method name="suspend"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
</class>
<class name="ViewAnimator"
extends="android.widget.FrameLayout"
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 78f90a1..adec5a4 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -96,6 +96,7 @@
run_command("NETWORK INTERFACES", 10, "netcfg", NULL);
dump_file("NETWORK ROUTES", "/proc/net/route");
+ dump_file("ARP CACHE", "/proc/net/arp");
#ifdef FWDUMP_bcm4329
run_command("DUMP WIFI FIRMWARE LOG", 60,
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0355016..0756c71 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -77,9 +77,12 @@
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
+import java.net.URL;
import java.util.ArrayList;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -460,6 +463,7 @@
mClassLoader =
ApplicationLoaders.getDefault().getClassLoader(
zip, mDataDir, mBaseClassLoader);
+ initializeJavaContextClassLoader();
} else {
if (mBaseClassLoader == null) {
mClassLoader = ClassLoader.getSystemClassLoader();
@@ -471,6 +475,120 @@
}
}
+ /**
+ * Setup value for Thread.getContextClassLoader(). If the
+ * package will not run in in a VM with other packages, we set
+ * the Java context ClassLoader to the
+ * PackageInfo.getClassLoader value. However, if this VM can
+ * contain multiple packages, we intead set the Java context
+ * ClassLoader to a proxy that will warn about the use of Java
+ * context ClassLoaders and then fall through to use the
+ * system ClassLoader.
+ *
+ * <p> Note that this is similar to but not the same as the
+ * android.content.Context.getClassLoader(). While both
+ * context class loaders are typically set to the
+ * PathClassLoader used to load the package archive in the
+ * single application per VM case, a single Android process
+ * may contain several Contexts executing on one thread with
+ * their own logical ClassLoaders while the Java context
+ * ClassLoader is a thread local. This is why in the case when
+ * we have multiple packages per VM we do not set the Java
+ * context ClassLoader to an arbitrary but instead warn the
+ * user to set their own if we detect that they are using a
+ * Java library that expects it to be set.
+ */
+ private void initializeJavaContextClassLoader() {
+ IPackageManager pm = getPackageManager();
+ android.content.pm.PackageInfo pi;
+ try {
+ pi = pm.getPackageInfo(mPackageName, 0);
+ } catch (RemoteException e) {
+ throw new AssertionError(e);
+ }
+ /*
+ * Two possible indications that this package could be
+ * sharing its virtual machine with other packages:
+ *
+ * 1.) the sharedUserId attribute is set in the manifest,
+ * indicating a request to share a VM with other
+ * packages with the same sharedUserId.
+ *
+ * 2.) the application element of the manifest has an
+ * attribute specifying a non-default process name,
+ * indicating the desire to run in another packages VM.
+ */
+ boolean sharedUserIdSet = (pi.sharedUserId != null);
+ boolean processNameNotDefault =
+ (pi.applicationInfo != null &&
+ !mPackageName.equals(pi.applicationInfo.processName));
+ boolean sharable = (sharedUserIdSet || processNameNotDefault);
+ ClassLoader contextClassLoader =
+ (sharable)
+ ? new WarningContextClassLoader()
+ : mClassLoader;
+ Thread.currentThread().setContextClassLoader(contextClassLoader);
+ }
+
+ private static class WarningContextClassLoader extends ClassLoader {
+
+ private static boolean warned = false;
+
+ private void warn(String methodName) {
+ if (warned) {
+ return;
+ }
+ warned = true;
+ Thread.currentThread().setContextClassLoader(getParent());
+ Log.w(TAG, "ClassLoader." + methodName + ": " +
+ "The class loader returned by " +
+ "Thread.getContextClassLoader() may fail for processes " +
+ "that host multiple applications. You should explicitly " +
+ "specify a context class loader. For example: " +
+ "Thread.setContextClassLoader(getClass().getClassLoader());");
+ }
+
+ @Override public URL getResource(String resName) {
+ warn("getResource");
+ return getParent().getResource(resName);
+ }
+
+ @Override public Enumeration<URL> getResources(String resName) throws IOException {
+ warn("getResources");
+ return getParent().getResources(resName);
+ }
+
+ @Override public InputStream getResourceAsStream(String resName) {
+ warn("getResourceAsStream");
+ return getParent().getResourceAsStream(resName);
+ }
+
+ @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
+ warn("loadClass");
+ return getParent().loadClass(className);
+ }
+
+ @Override public void setClassAssertionStatus(String cname, boolean enable) {
+ warn("setClassAssertionStatus");
+ getParent().setClassAssertionStatus(cname, enable);
+ }
+
+ @Override public void setPackageAssertionStatus(String pname, boolean enable) {
+ warn("setPackageAssertionStatus");
+ getParent().setPackageAssertionStatus(pname, enable);
+ }
+
+ @Override public void setDefaultAssertionStatus(boolean enable) {
+ warn("setDefaultAssertionStatus");
+ getParent().setDefaultAssertionStatus(enable);
+ }
+
+ @Override public void clearAssertionStatus() {
+ warn("clearAssertionStatus");
+ getParent().clearAssertionStatus();
+ }
+ }
+
public String getAppDir() {
return mAppDir;
}
diff --git a/core/java/android/backup/BackupManager.java b/core/java/android/backup/BackupManager.java
index 4bf59eb..07c08ff 100644
--- a/core/java/android/backup/BackupManager.java
+++ b/core/java/android/backup/BackupManager.java
@@ -47,9 +47,6 @@
public class BackupManager {
private static final String TAG = "BackupManager";
- /** @hide TODO: REMOVE THIS */
- public static final boolean EVEN_THINK_ABOUT_DOING_RESTORE = true;
-
private Context mContext;
private static IBackupManager sService;
@@ -78,9 +75,6 @@
* {@link android.app.BackupAgent} subclass will be scheduled when you call this method.
*/
public void dataChanged() {
- if (!EVEN_THINK_ABOUT_DOING_RESTORE) {
- return;
- }
checkServiceBinder();
if (sService != null) {
try {
@@ -100,9 +94,6 @@
* permission if the package named in the argument is not the caller's own.
*/
public static void dataChanged(String packageName) {
- if (!EVEN_THINK_ABOUT_DOING_RESTORE) {
- return;
- }
checkServiceBinder();
if (sService != null) {
try {
@@ -118,9 +109,6 @@
* {@link android.backup.RestoreSession} class for documentation on that process.
*/
public RestoreSession beginRestoreSession() {
- if (!EVEN_THINK_ABOUT_DOING_RESTORE) {
- return null;
- }
RestoreSession session = null;
checkServiceBinder();
if (sService != null) {
diff --git a/core/java/android/net/InterfaceConfiguration.java b/core/java/android/net/InterfaceConfiguration.java
index 9aa23fe..915c5d7 100644
--- a/core/java/android/net/InterfaceConfiguration.java
+++ b/core/java/android/net/InterfaceConfiguration.java
@@ -45,10 +45,10 @@
}
private static void putAddress(StringBuffer buf, int addr) {
- buf.append(addr & 0xff).append('.').
- append((addr >>>= 8) & 0xff).append('.').
- append((addr >>>= 8) & 0xff).append('.').
- append((addr >>>= 8) & 0xff);
+ buf.append((addr >> 24) & 0xff).append('.').
+ append((addr >> 16) & 0xff).append('.').
+ append((addr >> 8) & 0xff).append('.').
+ append(addr & 0xff);
}
/** Implement the Parcelable interface {@hide} */
diff --git a/core/java/android/pim/RecurrenceSet.java b/core/java/android/pim/RecurrenceSet.java
index 5d09fb5..635323e 100644
--- a/core/java/android/pim/RecurrenceSet.java
+++ b/core/java/android/pim/RecurrenceSet.java
@@ -18,7 +18,6 @@
import android.content.ContentValues;
import android.database.Cursor;
-import android.os.Bundle;
import android.provider.Calendar;
import android.text.TextUtils;
import android.text.format.Time;
@@ -26,6 +25,7 @@
import android.util.Log;
import java.util.List;
+import java.util.regex.Pattern;
/**
* Basic information about a recurrence, following RFC 2445 Section 4.8.5.
@@ -36,6 +36,7 @@
private final static String TAG = "CalendarProvider";
private final static String RULE_SEPARATOR = "\n";
+ private final static String FOLDING_SEPARATOR = "\n ";
// TODO: make these final?
public EventRecurrence[] rrules = null;
@@ -309,7 +310,8 @@
String rdateStr = values.getAsString(Calendar.Events.RDATE);
String exruleStr = values.getAsString(Calendar.Events.EXRULE);
String exdateStr = values.getAsString(Calendar.Events.EXDATE);
- boolean allDay = values.getAsInteger(Calendar.Events.ALL_DAY) == 1;
+ Integer allDayInteger = values.getAsInteger(Calendar.Events.ALL_DAY);
+ boolean allDay = (null != allDayInteger) ? (allDayInteger == 1) : false;
if ((dtstart == -1) ||
(TextUtils.isEmpty(duration))||
@@ -361,7 +363,7 @@
if (TextUtils.isEmpty(ruleStr)) {
return;
}
- String[] rrules = ruleStr.split(RULE_SEPARATOR);
+ String[] rrules = getRuleStrings(ruleStr);
for (String rrule : rrules) {
ICalendar.Property prop = new ICalendar.Property(propertyName);
prop.setValue(rrule);
@@ -369,6 +371,52 @@
}
}
+ private static String[] getRuleStrings(String ruleStr) {
+ if (null == ruleStr) {
+ return new String[0];
+ }
+ String unfoldedRuleStr = unfold(ruleStr);
+ String[] split = unfoldedRuleStr.split(RULE_SEPARATOR);
+ int count = split.length;
+ for (int n = 0; n < count; n++) {
+ split[n] = fold(split[n]);
+ }
+ return split;
+ }
+
+
+ private static final Pattern IGNORABLE_ICAL_WHITESPACE_RE =
+ Pattern.compile("(?:\\r\\n?|\\n)[ \t]");
+
+ private static final Pattern FOLD_RE = Pattern.compile(".{75}");
+
+ /**
+ * fold and unfolds ical content lines as per RFC 2445 section 4.1.
+ *
+ * <h3>4.1 Content Lines</h3>
+ *
+ * <p>The iCalendar object is organized into individual lines of text, called
+ * content lines. Content lines are delimited by a line break, which is a CRLF
+ * sequence (US-ASCII decimal 13, followed by US-ASCII decimal 10).
+ *
+ * <p>Lines of text SHOULD NOT be longer than 75 octets, excluding the line
+ * break. Long content lines SHOULD be split into a multiple line
+ * representations using a line "folding" technique. That is, a long line can
+ * be split between any two characters by inserting a CRLF immediately
+ * followed by a single linear white space character (i.e., SPACE, US-ASCII
+ * decimal 32 or HTAB, US-ASCII decimal 9). Any sequence of CRLF followed
+ * immediately by a single linear white space character is ignored (i.e.,
+ * removed) when processing the content type.
+ */
+ public static String fold(String unfoldedIcalContent) {
+ return FOLD_RE.matcher(unfoldedIcalContent).replaceAll("$0\r\n ");
+ }
+
+ public static String unfold(String foldedIcalContent) {
+ return IGNORABLE_ICAL_WHITESPACE_RE.matcher(
+ foldedIcalContent).replaceAll("");
+ }
+
private static void addPropertyForDateStr(ICalendar.Component component,
String propertyName,
String dateStr) {
diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java
index 2eb25954..194fe33 100644
--- a/core/java/android/pim/vcard/VCardComposer.java
+++ b/core/java/android/pim/vcard/VCardComposer.java
@@ -26,8 +26,6 @@
import android.net.Uri;
import android.os.RemoteException;
import android.pim.vcard.exception.VCardException;
-import android.provider.CallLog;
-import android.provider.CallLog.Calls;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
@@ -44,8 +42,6 @@
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
-import android.text.TextUtils;
-import android.text.format.Time;
import android.util.CharsetUtils;
import android.util.Log;
@@ -60,7 +56,6 @@
import java.lang.reflect.Method;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -125,12 +120,6 @@
public static final String VCARD_TYPE_STRING_DOCOMO = "docomo";
- // Property for call log entry
- private static final String VCARD_PROPERTY_X_TIMESTAMP = "X-IRMC-CALL-DATETIME";
- private static final String VCARD_PROPERTY_CALLTYPE_INCOMING = "INCOMING";
- private static final String VCARD_PROPERTY_CALLTYPE_OUTGOING = "OUTGOING";
- private static final String VCARD_PROPERTY_CALLTYPE_MISSED = "MISSED";
-
private static final String SHIFT_JIS = "SHIFT_JIS";
private static final String UTF_8 = "UTF-8";
@@ -275,30 +264,14 @@
private final String mCharsetString;
private boolean mTerminateIsCalled;
- final private List<OneEntryHandler> mHandlerList;
+ private final List<OneEntryHandler> mHandlerList;
private String mErrorReason = NO_ERROR;
- private boolean mIsCallLogComposer;
-
private static final String[] sContactsProjection = new String[] {
Contacts._ID,
};
- /** The projection to use when querying the call log table */
- private static final String[] sCallLogProjection = new String[] {
- Calls.NUMBER, Calls.DATE, Calls.TYPE, Calls.CACHED_NAME, Calls.CACHED_NUMBER_TYPE,
- Calls.CACHED_NUMBER_LABEL
- };
- private static final int NUMBER_COLUMN_INDEX = 0;
- private static final int DATE_COLUMN_INDEX = 1;
- private static final int CALL_TYPE_COLUMN_INDEX = 2;
- private static final int CALLER_NAME_COLUMN_INDEX = 3;
- private static final int CALLER_NUMBERTYPE_COLUMN_INDEX = 4;
- private static final int CALLER_NUMBERLABEL_COLUMN_INDEX = 5;
-
- private static final String FLAG_TIMEZONE_UTC = "Z";
-
public VCardComposer(Context context) {
this(context, VCardConfig.VCARD_TYPE_DEFAULT, true);
}
@@ -377,6 +350,7 @@
if (contentUri == null) {
return false;
}
+
if (mCareHandlerErrors) {
List<OneEntryHandler> finishedList = new ArrayList<OneEntryHandler>(
mHandlerList.size());
@@ -396,10 +370,7 @@
}
final String[] projection;
- if (CallLog.Calls.CONTENT_URI.equals(contentUri)) {
- projection = sCallLogProjection;
- mIsCallLogComposer = true;
- } else if (Contacts.CONTENT_URI.equals(contentUri) ||
+ if (Contacts.CONTENT_URI.equals(contentUri) ||
CONTACTS_TEST_CONTENT_URI.equals(contentUri)) {
projection = sContactsProjection;
} else {
@@ -426,11 +397,7 @@
return false;
}
- if (mIsCallLogComposer) {
- mIdColumn = -1;
- } else {
- mIdColumn = mCursor.getColumnIndex(Contacts._ID);
- }
+ mIdColumn = mCursor.getColumnIndex(Contacts._ID);
return true;
}
@@ -448,19 +415,14 @@
mErrorReason = FAILURE_REASON_NOT_INITIALIZED;
return false;
}
- String name = null;
String vcard;
try {
- if (mIsCallLogComposer) {
- vcard = createOneCallLogEntryInternal();
+ if (mIdColumn >= 0) {
+ vcard = createOneEntryInternal(mCursor.getString(mIdColumn),
+ getEntityIteratorMethod);
} else {
- if (mIdColumn >= 0) {
- vcard = createOneEntryInternal(mCursor.getString(mIdColumn),
- getEntityIteratorMethod);
- } else {
- Log.e(LOG_TAG, "Incorrect mIdColumn: " + mIdColumn);
- return true;
- }
+ Log.e(LOG_TAG, "Incorrect mIdColumn: " + mIdColumn);
+ return true;
}
} catch (VCardException e) {
Log.e(LOG_TAG, "VCardException has been thrown: " + e.getMessage());
@@ -468,7 +430,7 @@
} catch (OutOfMemoryError error) {
// Maybe some data (e.g. photo) is too big to have in memory. But it
// should be rare.
- Log.e(LOG_TAG, "OutOfMemoryError occured. Ignore the entry: " + name);
+ Log.e(LOG_TAG, "OutOfMemoryError occured. Ignore the entry.");
System.gc();
// TODO: should tell users what happened?
return true;
@@ -630,99 +592,4 @@
public String getErrorReason() {
return mErrorReason;
}
-
- /**
- * This static function is to compose vCard for phone own number
- */
- public String composeVCardForPhoneOwnNumber(int phonetype, String phoneName,
- String phoneNumber, boolean vcardVer21) {
- final int vcardType = (vcardVer21 ?
- VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8 :
- VCardConfig.VCARD_TYPE_V30_GENERIC_UTF8);
- final VCardBuilder builder = new VCardBuilder(vcardType);
- boolean needCharset = false;
- if (!(VCardUtils.containsOnlyPrintableAscii(phoneName))) {
- needCharset = true;
- }
- builder.appendLine(VCardConstants.PROPERTY_FN, phoneName, needCharset, false);
- builder.appendLine(VCardConstants.PROPERTY_N, phoneName, needCharset, false);
-
- if (!TextUtils.isEmpty(phoneNumber)) {
- String label = Integer.toString(phonetype);
- builder.appendTelLine(phonetype, label, phoneNumber, false);
- }
-
- return builder.toString();
- }
-
- /**
- * Format according to RFC 2445 DATETIME type.
- * The format is: ("%Y%m%dT%H%M%SZ").
- */
- private final String toRfc2455Format(final long millSecs) {
- Time startDate = new Time();
- startDate.set(millSecs);
- String date = startDate.format2445();
- return date + FLAG_TIMEZONE_UTC;
- }
-
- /**
- * Try to append the property line for a call history time stamp field if possible.
- * Do nothing if the call log type gotton from the database is invalid.
- */
- private void tryAppendCallHistoryTimeStampField(final VCardBuilder builder) {
- // Extension for call history as defined in
- // in the Specification for Ic Mobile Communcation - ver 1.1,
- // Oct 2000. This is used to send the details of the call
- // history - missed, incoming, outgoing along with date and time
- // to the requesting device (For example, transferring phone book
- // when connected over bluetooth)
- //
- // e.g. "X-IRMC-CALL-DATETIME;MISSED:20050320T100000Z"
- final int callLogType = mCursor.getInt(CALL_TYPE_COLUMN_INDEX);
- final String callLogTypeStr;
- switch (callLogType) {
- case Calls.INCOMING_TYPE: {
- callLogTypeStr = VCARD_PROPERTY_CALLTYPE_INCOMING;
- break;
- }
- case Calls.OUTGOING_TYPE: {
- callLogTypeStr = VCARD_PROPERTY_CALLTYPE_OUTGOING;
- break;
- }
- case Calls.MISSED_TYPE: {
- callLogTypeStr = VCARD_PROPERTY_CALLTYPE_MISSED;
- break;
- }
- default: {
- Log.w(LOG_TAG, "Call log type not correct.");
- return;
- }
- }
-
- final long dateAsLong = mCursor.getLong(DATE_COLUMN_INDEX);
- builder.appendLine(VCARD_PROPERTY_X_TIMESTAMP,
- Arrays.asList(callLogTypeStr), toRfc2455Format(dateAsLong));
- }
-
- private String createOneCallLogEntryInternal() {
- final VCardBuilder builder = new VCardBuilder(VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
- String name = mCursor.getString(CALLER_NAME_COLUMN_INDEX);
- if (TextUtils.isEmpty(name)) {
- name = mCursor.getString(NUMBER_COLUMN_INDEX);
- }
- final boolean needCharset = !(VCardUtils.containsOnlyPrintableAscii(name));
- builder.appendLine(VCardConstants.PROPERTY_FN, name, needCharset, false);
- builder.appendLine(VCardConstants.PROPERTY_N, name, needCharset, false);
-
- final String number = mCursor.getString(NUMBER_COLUMN_INDEX);
- final int type = mCursor.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX);
- String label = mCursor.getString(CALLER_NUMBERLABEL_COLUMN_INDEX);
- if (TextUtils.isEmpty(label)) {
- label = Integer.toString(type);
- }
- builder.appendTelLine(type, label, number, false);
- tryAppendCallHistoryTimeStampField(builder);
- return builder.toString();
- }
}
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 2eebe77..caa3144 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -16,20 +16,14 @@
package android.server.search;
-import android.app.ActivityManagerNative;
-import android.app.IActivityWatcher;
+import com.android.internal.content.PackageMonitor;
+
import android.app.ISearchManager;
-import android.app.ISearchManagerCallback;
import android.app.SearchManager;
import android.app.SearchableInfo;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
import android.util.Log;
import java.util.List;
@@ -42,13 +36,11 @@
// general debugging support
private static final String TAG = "SearchManagerService";
- private static final boolean DBG = false;
// Context that the service is running in.
private final Context mContext;
- // This field is initialized in ensureSearchablesCreated(), and then never modified.
- // Only accessed by ensureSearchablesCreated() and getSearchables()
+ // This field is initialized lazily in getSearchables(), and then never modified.
private Searchables mSearchables;
/**
@@ -61,58 +53,28 @@
mContext = context;
}
- private synchronized void ensureSearchablesCreated() {
- if (mSearchables != null) return; // already created
-
- mSearchables = new Searchables(mContext);
- mSearchables.buildSearchableList();
-
- IntentFilter packageFilter = new IntentFilter();
- packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
- packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- packageFilter.addDataScheme("package");
- mContext.registerReceiver(mPackageChangedReceiver, packageFilter);
- // Register for events related to sdcard installation.
- IntentFilter sdFilter = new IntentFilter();
- sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
- sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- mContext.registerReceiver(mPackageChangedReceiver, sdFilter);
- }
-
private synchronized Searchables getSearchables() {
- ensureSearchablesCreated();
+ if (mSearchables == null) {
+ mSearchables = new Searchables(mContext);
+ mSearchables.buildSearchableList();
+ new MyPackageMonitor().register(mContext, true);
+ }
return mSearchables;
}
/**
* Refreshes the "searchables" list when packages are added/removed.
*/
- private BroadcastReceiver mPackageChangedReceiver = new BroadcastReceiver() {
+ class MyPackageMonitor extends PackageMonitor {
@Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
-
- if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
- Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
- Intent.ACTION_PACKAGE_CHANGED.equals(action) ||
- Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action) ||
- Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
- if (DBG) Log.d(TAG, "Got " + action);
- // Update list of searchable activities
- getSearchables().buildSearchableList();
- broadcastSearchablesChanged();
- }
+ public void onSomePackagesChanged() {
+ // Update list of searchable activities
+ getSearchables().buildSearchableList();
+ // Inform all listeners that the list of searchables has been updated.
+ Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ mContext.sendBroadcast(intent);
}
- };
-
- /**
- * Informs all listeners that the list of searchables has been updated.
- */
- void broadcastSearchablesChanged() {
- Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- mContext.sendBroadcast(intent);
}
//
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 6c89f92..6de9c65 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -1012,12 +1012,12 @@
int extra;
if (needMultiply) {
- // XXX: this looks like it is using the +0.5 and the cast to int
- // to do rounding, but this I expect this isn't doing the intended
- // thing when spacingmult < 1. An intended extra of, say, -1.2
- // will get 'rounded' to -.7 and then truncated to 0.
- extra = (int) ((below - above) * (spacingmult - 1)
- + spacingadd + 0.5);
+ double ex = (below - above) * (spacingmult - 1) + spacingadd;
+ if (ex >= 0) {
+ extra = (int)(ex + 0.5);
+ } else {
+ extra = -(int)(-ex + 0.5);
+ }
} else {
extra = 0;
}
diff --git a/core/java/android/webkit/PluginManager.java b/core/java/android/webkit/PluginManager.java
index cdcb662..df7d0c4 100644
--- a/core/java/android/webkit/PluginManager.java
+++ b/core/java/android/webkit/PluginManager.java
@@ -165,6 +165,7 @@
continue;
}
+/* temporarily disable signatures checking
// check to ensure the plugin is properly signed
Signature signatures[] = pkgInfo.signatures;
if (signatures == null) {
@@ -184,7 +185,7 @@
continue;
}
}
-
+*/
// determine the type of plugin from the manifest
if (serviceInfo.metaData == null) {
Log.e(LOGTAG, "The plugin '" + serviceInfo.name + "' has no type defined");
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 906bca1..c2517a8 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -62,6 +62,8 @@
private static final int STATE_PLAYING = 3;
private static final int STATE_PAUSED = 4;
private static final int STATE_PLAYBACK_COMPLETED = 5;
+ private static final int STATE_SUSPEND = 6;
+ private static final int STATE_RESUME = 7;
// mCurrentState is a VideoView object's current state.
// mTargetState is the state that a method caller intends to reach.
@@ -87,6 +89,7 @@
private boolean mCanPause;
private boolean mCanSeekBack;
private boolean mCanSeekForward;
+ private int mStateWhenSuspended; //state before calling suspend()
public VideoView(Context context) {
super(context);
@@ -466,7 +469,14 @@
public void surfaceCreated(SurfaceHolder holder)
{
mSurfaceHolder = holder;
- openVideo();
+ //resume() was called before surfaceCreated()
+ if (mMediaPlayer != null && mCurrentState == STATE_SUSPEND
+ && mTargetState == STATE_RESUME) {
+ mMediaPlayer.setDisplay(mSurfaceHolder);
+ resume();
+ } else {
+ openVideo();
+ }
}
public void surfaceDestroyed(SurfaceHolder holder)
@@ -474,7 +484,6 @@
// after we return from this we can't use the surface any more
mSurfaceHolder = null;
if (mMediaController != null) mMediaController.hide();
- release(true);
}
};
@@ -567,7 +576,36 @@
mTargetState = STATE_PAUSED;
}
- // cache duration as mDuration for faster access
+ public void suspend() {
+ if (isInPlaybackState()) {
+ if (mMediaPlayer.suspend()) {
+ mStateWhenSuspended = mCurrentState;
+ mCurrentState = STATE_SUSPEND;
+ mTargetState = STATE_SUSPEND;
+ } else {
+ Log.w(TAG, "Unable to suspend video");
+ mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
+ }
+ }
+ }
+
+ public void resume() {
+ if (mSurfaceHolder == null && mCurrentState == STATE_SUSPEND){
+ mTargetState = STATE_RESUME;
+ return;
+ }
+ if (mMediaPlayer != null && mCurrentState == STATE_SUSPEND) {
+ if (mMediaPlayer.resume()) {
+ mCurrentState = mStateWhenSuspended;
+ mTargetState = mStateWhenSuspended;
+ } else {
+ Log.w(TAG, "Unable to resume video");
+ mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
+ }
+ }
+ }
+
+ // cache duration as mDuration for faster access
public int getDuration() {
if (isInPlaybackState()) {
if (mDuration > 0) {
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index a82a21e..5afa0342 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1466,19 +1466,25 @@
for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
value = bag->map.value;
jstring str = NULL;
-
+
// Take care of resolving the found resource to its final value.
ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
if (value.dataType == Res_value::TYPE_STRING) {
- const char16_t* str16 = res.getTableStringBlock(block)->stringAt(value.data, &strLen);
- str = env->NewString(str16, strLen);
- if (str == NULL) {
- doThrow(env, "java/lang/OutOfMemoryError");
- res.unlockBag(startOfBag);
- return NULL;
+ const ResStringPool* pool = res.getTableStringBlock(block);
+ const char* str8 = pool->string8At(value.data, &strLen);
+ if (str8 != NULL) {
+ str = env->NewStringUTF(str8);
+ } else {
+ const char16_t* str16 = pool->stringAt(value.data, &strLen);
+ str = env->NewString(str16, strLen);
+ if (str == NULL) {
+ doThrow(env, "java/lang/OutOfMemoryError");
+ res.unlockBag(startOfBag);
+ return NULL;
+ }
}
}
-
+
env->SetObjectArrayElement(array, i, str);
}
res.unlockBag(startOfBag);
diff --git a/core/jni/android_util_StringBlock.cpp b/core/jni/android_util_StringBlock.cpp
index ffb271c..641fbce 100644
--- a/core/jni/android_util_StringBlock.cpp
+++ b/core/jni/android_util_StringBlock.cpp
@@ -89,6 +89,11 @@
}
size_t len;
+ const char* str8 = osb->string8At(idx, &len);
+ if (str8 != NULL) {
+ return env->NewStringUTF(str8);
+ }
+
const char16_t* str = osb->stringAt(idx, &len);
if (str == NULL) {
doThrow(env, "java/lang/IndexOutOfBoundsException");
diff --git a/core/res/res/drawable-hdpi/spinnerbox_arrow_first.9.png b/core/res/res/drawable-hdpi/spinnerbox_arrow_first.9.png
deleted file mode 100644
index af80855..0000000
--- a/core/res/res/drawable-hdpi/spinnerbox_arrow_first.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinnerbox_arrow_last.9.png b/core/res/res/drawable-hdpi/spinnerbox_arrow_last.9.png
deleted file mode 100644
index dc47275..0000000
--- a/core/res/res/drawable-hdpi/spinnerbox_arrow_last.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinnerbox_arrow_middle.9.png b/core/res/res/drawable-hdpi/spinnerbox_arrow_middle.9.png
deleted file mode 100644
index 007f279..0000000
--- a/core/res/res/drawable-hdpi/spinnerbox_arrow_middle.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinnerbox_arrow_single.9.png b/core/res/res/drawable-hdpi/spinnerbox_arrow_single.9.png
deleted file mode 100644
index 24592a3..0000000
--- a/core/res/res/drawable-hdpi/spinnerbox_arrow_single.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinnerbox_arrow_first.9.png b/core/res/res/drawable-mdpi/spinnerbox_arrow_first.9.png
deleted file mode 100644
index d8e268d..0000000
--- a/core/res/res/drawable-mdpi/spinnerbox_arrow_first.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinnerbox_arrow_last.9.png b/core/res/res/drawable-mdpi/spinnerbox_arrow_last.9.png
deleted file mode 100644
index 087e650..0000000
--- a/core/res/res/drawable-mdpi/spinnerbox_arrow_last.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinnerbox_arrow_middle.9.png b/core/res/res/drawable-mdpi/spinnerbox_arrow_middle.9.png
deleted file mode 100644
index f1f2ff5..0000000
--- a/core/res/res/drawable-mdpi/spinnerbox_arrow_middle.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinnerbox_arrow_single.9.png b/core/res/res/drawable-mdpi/spinnerbox_arrow_single.9.png
deleted file mode 100644
index f537b3b..0000000
--- a/core/res/res/drawable-mdpi/spinnerbox_arrow_single.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/spinnerbox_arrows.xml b/core/res/res/drawable/spinnerbox_arrows.xml
deleted file mode 100644
index 276a0f0..0000000
--- a/core/res/res/drawable/spinnerbox_arrows.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/res/drawable/spinnerbox_arrows.xml
-**
-** Copyright 2007, 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.
-*/
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_single="true" android:drawable="@drawable/spinnerbox_arrow_single" />
- <item android:state_first="true" android:drawable="@drawable/spinnerbox_arrow_first" />
- <item android:state_last="true" android:drawable="@drawable/spinnerbox_arrow_last" />
- <item android:state_middle="true" android:drawable="@drawable/spinnerbox_arrow_middle" />
- <item android:state_pressed="true" android:drawable="@drawable/spinnerbox_arrow_single" />
-</selector>
diff --git a/core/res/res/layout/status_bar_expanded.xml b/core/res/res/layout/status_bar_expanded.xml
index a0cd11d..30138a7 100644
--- a/core/res/res/layout/status_bar_expanded.xml
+++ b/core/res/res/layout/status_bar_expanded.xml
@@ -20,9 +20,9 @@
<com.android.server.status.ExpandedView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
- android:background="@drawable/status_bar_background"
android:focusable="true"
- android:descendantFocusability="afterDescendants">
+ android:descendantFocusability="afterDescendants"
+ >
<LinearLayout
android:layout_width="match_parent"
@@ -79,19 +79,18 @@
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_weight="1"
>
<ScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
+ android:layout_height="match_parent"
android:fadingEdge="none"
>
<com.android.server.status.NotificationLinearLayout
android:id="@+id/notificationLinearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_weight="1"
android:orientation="vertical"
>
@@ -136,7 +135,7 @@
<ImageView
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:src="@drawable/title_bar_shadow"
android:scaleType="fitXY"
/>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f1501ae..5d2d272 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -779,18 +779,18 @@
applications can use this to read phone owner data.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_readCalendar">read calendar data</string>
+ <string name="permlab_readCalendar">read calendar events</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readCalendar">Allows an application to read all
of the calendar events stored on your phone. Malicious applications
can use this to send your calendar events to other people.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_writeCalendar">write calendar data</string>
+ <string name="permlab_writeCalendar">add or modify calendar events and send email to guests</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_writeCalendar">Allows an application to modify the
- calendar events stored on your phone. Malicious
- applications can use this to erase or modify your calendar data.</string>
+ <string name="permdesc_writeCalendar">Allows an application to add or change the
+ events on your calendar, which may send email to guests. Malicious applications can use this
+ to erase or modify your calendar events or to send email to guests.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_accessMockLocation">mock location sources for testing</string>
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java
index 1e4db3d..7511ec1 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java
@@ -213,13 +213,13 @@
}
public int scale(float height) {
- int altVal = (int)(height * sMult + sAdd + 0.5); // existing impl
+ int altVal = (int)(height * sMult + sAdd + 0.5);
int rndVal = Math.round(height * sMult + sAdd);
if (altVal != rndVal) {
Log.i("Scale", "expected scale: " + rndVal +
" != returned scale: " + altVal);
}
- return altVal; // existing implementation
+ return rndVal;
}
}
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index 13ea27e..cd657e8 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -447,6 +447,8 @@
}
const char16_t* stringAt(size_t idx, size_t* outLen) const;
+ const char* string8At(size_t idx, size_t* outLen) const;
+
const ResStringPool_span* styleAt(const ResStringPool_ref& ref) const;
const ResStringPool_span* styleAt(size_t idx) const;
diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp
index 096aa73..42b6508 100644
--- a/libs/audioflinger/AudioPolicyManagerBase.cpp
+++ b/libs/audioflinger/AudioPolicyManagerBase.cpp
@@ -295,13 +295,31 @@
if (oldState == AudioSystem::MODE_IN_CALL && newDevice == 0) {
newDevice = hwOutputDesc->device();
}
+
+ // when changing from ring tone to in call mode, mute the ringing tone
+ // immediately and delay the route change to avoid sending the ring tone
+ // tail into the earpiece or headset.
+ int delayMs = 0;
+ if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) {
+ // delay the device change command by twice the output latency to have some margin
+ // and be sure that audio buffers not yet affected by the mute are out when
+ // we actually apply the route change
+ delayMs = hwOutputDesc->mLatency*2;
+ setStreamMute(AudioSystem::RING, true, mHardwareOutput);
+ }
+
// change routing is necessary
- setOutputDevice(mHardwareOutput, newDevice, force);
+ setOutputDevice(mHardwareOutput, newDevice, force, delayMs);
// if entering in call state, handle special case of active streams
// pertaining to sonification strategy see handleIncallSonification()
if (state == AudioSystem::MODE_IN_CALL) {
LOGV("setPhoneState() in call state management: new state is %d", state);
+ // unmute the ringing tone after a sufficient delay if it was muted before
+ // setting output device above
+ if (oldState == AudioSystem::MODE_RINGTONE) {
+ setStreamMute(AudioSystem::RING, false, mHardwareOutput, MUTE_TIME_MS);
+ }
for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
handleIncallSonification(stream, true, true);
}
@@ -1207,10 +1225,10 @@
return INVALID_OPERATION;
}
- // mute media during 2 seconds to avoid outputing sound on hardware output while music stream
+ // mute media strategy to avoid outputting sound on hardware output while music stream
// is switched from A2DP output and before music is paused by music application
setStrategyMute(STRATEGY_MEDIA, true, mHardwareOutput);
- setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, 2000);
+ setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, MUTE_TIME_MS);
if (!a2dpUsedForSonification()) {
// unmute music on A2DP output if a notification or ringtone is playing
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index e8bd5cf..38600b9 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -497,6 +497,34 @@
return NULL;
}
+const char* ResStringPool::string8At(size_t idx, size_t* outLen) const
+{
+ if (mError == NO_ERROR && idx < mHeader->stringCount) {
+ const bool isUTF8 = (mHeader->flags&ResStringPool_header::UTF8_FLAG) != 0;
+ const uint32_t off = mEntries[idx]/(isUTF8?sizeof(char):sizeof(char16_t));
+ if (off < (mStringPoolSize-1)) {
+ if (isUTF8) {
+ const uint8_t* strings = (uint8_t*)mStrings;
+ const uint8_t* str = strings+off;
+ DECODE_LENGTH(str, sizeof(uint8_t), *outLen)
+ size_t encLen;
+ DECODE_LENGTH(str, sizeof(uint8_t), encLen)
+ if ((uint32_t)(str+encLen-strings) < mStringPoolSize) {
+ return (const char*)str;
+ } else {
+ LOGW("Bad string block: string #%d extends to %d, past end at %d\n",
+ (int)idx, (int)(str+encLen-strings), (int)mStringPoolSize);
+ }
+ }
+ } else {
+ LOGW("Bad string block: string #%d entry is at %d, past end at %d\n",
+ (int)idx, (int)(off*sizeof(uint16_t)),
+ (int)(mStringPoolSize*sizeof(uint16_t)));
+ }
+ }
+ return NULL;
+}
+
const ResStringPool_span* ResStringPool::styleAt(const ResStringPool_ref& ref) const
{
return styleAt(ref.index);
@@ -4018,14 +4046,19 @@
printf("(attribute) 0x%08x\n", value.data);
} else if (value.dataType == Res_value::TYPE_STRING) {
size_t len;
- const char16_t* str = pkg->header->values.stringAt(
+ const char* str8 = pkg->header->values.string8At(
value.data, &len);
- if (str == NULL) {
- printf("(string) null\n");
+ if (str8 != NULL) {
+ printf("(string8) \"%s\"\n", str8);
} else {
- printf("(string%d) \"%s\"\n",
- pkg->header->values.isUTF8()?8:16,
- String8(str, len).string());
+ const char16_t* str16 = pkg->header->values.stringAt(
+ value.data, &len);
+ if (str16 != NULL) {
+ printf("(string16) \"%s\"\n",
+ String8(str16, len).string());
+ } else {
+ printf("(string) null\n");
+ }
}
} else if (value.dataType == Res_value::TYPE_FLOAT) {
printf("(float) %g\n", *(const float*)&value.data);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
index 717f7ba..d7cf069 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
@@ -1,28 +1,35 @@
package com.android.mediaframeworktest;
import android.media.MediaRecorder;
+import android.media.EncoderCapabilities;
+import android.media.EncoderCapabilities.VideoEncoderCap;
+import android.media.EncoderCapabilities.AudioEncoderCap;
+import android.media.DecoderCapabilities;
+import android.media.DecoderCapabilities.VideoDecoder;
+import android.media.DecoderCapabilities.AudioDecoder;
+
import android.os.SystemProperties;
+import java.util.List;
import java.util.HashMap;
-public class MediaProfileReader {
+public class MediaProfileReader
+{
+ private static final List<VideoDecoder> videoDecoders = DecoderCapabilities.getVideoDecoders();
+ private static final List<AudioDecoder> audioDecoders = DecoderCapabilities.getAudioDecoders();
+ private static final List<VideoEncoderCap> videoEncoders = EncoderCapabilities.getVideoEncoders();
+ private static final List<AudioEncoderCap> audioEncoders = EncoderCapabilities.getAudioEncoders();
+ private static final HashMap<Integer, String> encoderMap = new HashMap<Integer, String>();
- public static final HashMap<String, Integer>
- OUTPUT_FORMAT_TABLE = new HashMap<String, Integer>();
- public static String MEDIA_ENC_VID = "ro.media.enc.vid.";
- public static String MEDIA_AUD_VID = "ro.media.enc.aud.";
- public static String[] VIDEO_ENCODER_PROPERTY = {".width", ".height", ".bps", ".fps",};
- public static String[] AUDIO_ENCODER_PROPERTY = {".bps", ".hz", ".ch",};
+ static {
+ initEncoderMap();
+ };
- public static String getVideoCodecProperty() {
- String s;
- s = SystemProperties.get("ro.media.enc.vid.codec");
- return s;
+ public static List<VideoEncoderCap> getVideoEncoders() {
+ return videoEncoders;
}
- public static String getAudioCodecProperty() {
- String s;
- s = SystemProperties.get("ro.media.enc.aud.codec");
- return s;
+ public static List<AudioEncoderCap> getAudioEncoders() {
+ return audioEncoders;
}
public static String getDeviceType() {
@@ -33,78 +40,56 @@
}
public static boolean getWMAEnable() {
- // push all the property into one big table
- int wmaEnable = 1;
- wmaEnable = SystemProperties.getInt("ro.media.dec.aud.wma.enabled",
- wmaEnable);
- if (wmaEnable == 1) {
- return true;
- } else {
- return false;
+ for (AudioDecoder decoder: audioDecoders) {
+ if (decoder == AudioDecoder.AUDIO_DECODER_WMA) {
+ return true;
+ }
}
+ return false;
}
public static boolean getWMVEnable(){
- int wmvEnable = 1;
- wmvEnable = SystemProperties.getInt("ro.media.dec.vid.wmv.enabled",
- wmvEnable);
- if (wmvEnable == 1) {
- return true;
- } else {
- return false;
- }
- }
-
- public static void createVideoProfileTable() {
- // push all the property into one big table
- String encoderType = getVideoCodecProperty();
- if (encoderType.length() != 0) {
- String encoder[] = encoderType.split(",");
- for (int i = 0; i < encoder.length; i++) {
- for (int j = 0; j < VIDEO_ENCODER_PROPERTY.length; j++) {
- String propertyName = MEDIA_ENC_VID + encoder[i] + VIDEO_ENCODER_PROPERTY[j];
- String prop = SystemProperties.get(propertyName);
- // push to the table
- String propRange[] = prop.split(",");
- OUTPUT_FORMAT_TABLE.put((encoder[i] + VIDEO_ENCODER_PROPERTY[j] + "_low"),
- Integer.parseInt(propRange[0]));
- OUTPUT_FORMAT_TABLE.put((encoder[i] + VIDEO_ENCODER_PROPERTY[j] + "_high"),
- Integer.parseInt(propRange[1]));
- }
-
+ for (VideoDecoder decoder: videoDecoders) {
+ if (decoder == VideoDecoder.VIDEO_DECODER_WMV) {
+ return true;
}
}
+ return false;
}
- public static void createAudioProfileTable() {
- // push all the property into one big table
- String audioType = getAudioCodecProperty();
- String encoder[] = audioType.split(",");
- if (audioType.length() != 0) {
- for (int i = 0; i < encoder.length; i++) {
- for (int j = 0; j < AUDIO_ENCODER_PROPERTY.length; j++) {
- String propertyName = MEDIA_AUD_VID + encoder[i] + AUDIO_ENCODER_PROPERTY[j];
- String prop = SystemProperties.get(propertyName);
- // push to the table
- String propRange[] = prop.split(",");
- OUTPUT_FORMAT_TABLE.put((encoder[i] + AUDIO_ENCODER_PROPERTY[j] + "_low"),
- Integer.parseInt(propRange[0]));
- OUTPUT_FORMAT_TABLE.put((encoder[i] + AUDIO_ENCODER_PROPERTY[j] + "_high"),
- Integer.parseInt(propRange[1]));
- }
- }
+ public static String getVideoCodecName(int videoEncoder) {
+ if (videoEncoder != MediaRecorder.VideoEncoder.H263 &&
+ videoEncoder != MediaRecorder.VideoEncoder.H264 &&
+ videoEncoder != MediaRecorder.VideoEncoder.MPEG_4_SP) {
+ throw new IllegalArgumentException("Unsupported video encoder " + videoEncoder);
}
+ return encoderMap.get(videoEncoder);
}
- public static void createEncoderTable(){
- OUTPUT_FORMAT_TABLE.put("h263", MediaRecorder.VideoEncoder.H263);
- OUTPUT_FORMAT_TABLE.put("h264", MediaRecorder.VideoEncoder.H264);
- OUTPUT_FORMAT_TABLE.put("m4v", MediaRecorder.VideoEncoder.MPEG_4_SP);
- OUTPUT_FORMAT_TABLE.put("amrnb", MediaRecorder.AudioEncoder.AMR_NB);
- OUTPUT_FORMAT_TABLE.put("amrwb", MediaRecorder.AudioEncoder.AMR_WB);
- OUTPUT_FORMAT_TABLE.put("aac", MediaRecorder.AudioEncoder.AAC);
- OUTPUT_FORMAT_TABLE.put("aacplus", MediaRecorder.AudioEncoder.AAC_PLUS);
- OUTPUT_FORMAT_TABLE.put("eaacplus",
- MediaRecorder.AudioEncoder.EAAC_PLUS);
+ public static String getAudioCodecName(int audioEncoder) {
+ if (audioEncoder != MediaRecorder.AudioEncoder.AMR_NB &&
+ audioEncoder != MediaRecorder.AudioEncoder.AMR_WB &&
+ audioEncoder != MediaRecorder.AudioEncoder.AAC &&
+ audioEncoder != MediaRecorder.AudioEncoder.AAC_PLUS &&
+ audioEncoder != MediaRecorder.AudioEncoder.EAAC_PLUS) {
+ throw new IllegalArgumentException("Unsupported audio encodeer " + audioEncoder);
+ }
+ return encoderMap.get(audioEncoder);
+ }
+
+ private MediaProfileReader() {} // Don't call me
+
+ private static void initEncoderMap() {
+ // video encoders
+ encoderMap.put(MediaRecorder.VideoEncoder.H263, "h263");
+ encoderMap.put(MediaRecorder.VideoEncoder.H264, "h264");
+ encoderMap.put(MediaRecorder.VideoEncoder.MPEG_4_SP, "m4v");
+
+ // audio encoders
+ encoderMap.put(MediaRecorder.AudioEncoder.AMR_NB, "amrnb");
+ encoderMap.put(MediaRecorder.AudioEncoder.AMR_WB, "amrwb");
+ encoderMap.put(MediaRecorder.AudioEncoder.AAC, "aac");
+ encoderMap.put(MediaRecorder.AudioEncoder.AAC_PLUS, "aacplus");
+ encoderMap.put(MediaRecorder.AudioEncoder.EAAC_PLUS, "eaacplus");
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
index fdc5970..39caccd 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
@@ -25,6 +25,9 @@
import android.hardware.Camera;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
+import android.media.EncoderCapabilities;
+import android.media.EncoderCapabilities.VideoEncoderCap;
+import android.media.EncoderCapabilities.AudioEncoderCap;
import android.test.ActivityInstrumentationTestCase;
import android.util.Log;
import android.view.SurfaceHolder;
@@ -33,6 +36,7 @@
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.Suppress;
+import java.util.List;
/**
@@ -99,31 +103,29 @@
}
}
- private boolean recordVideoWithPara(String encoder, String audio, String quality){
+ private boolean recordVideoWithPara(VideoEncoderCap videoCap, AudioEncoderCap audioCap, boolean highQuality){
boolean recordSuccess = false;
- int videoEncoder = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder);
- int audioEncoder = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio);
- int videoWidth = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".width_" + quality);
- int videoHeight =
- MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".height_" + quality);
- int videoFps = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".fps_" + quality);
- int videoBitrate = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".bps_" + quality);
- int audioBitrate = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio + ".bps_" + quality);
- int audioChannels = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio + ".ch_" + quality);
- int audioSamplingRate =
- MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio + ".hz_" + quality);
+ int videoEncoder = videoCap.mCodec;
+ int audioEncoder = audioCap.mCodec;
+ int videoWidth = highQuality? videoCap.mMaxFrameWidth: videoCap.mMinFrameWidth;
+ int videoHeight = highQuality? videoCap.mMaxFrameHeight: videoCap.mMinFrameHeight;
+ int videoFps = highQuality? videoCap.mMaxFrameRate: videoCap.mMinFrameRate;
+ int videoBitrate = highQuality? videoCap.mMaxBitRate: videoCap.mMinBitRate;
+ int audioBitrate = highQuality? audioCap.mMaxBitRate: audioCap.mMinBitRate;
+ int audioChannels = highQuality? audioCap.mMaxChannels: audioCap.mMinChannels ;
+ int audioSamplingRate = highQuality? audioCap.mMaxSampleRate: audioCap.mMinSampleRate;
if (videoFps < MIN_VIDEO_FPS) {
videoFps = MIN_VIDEO_FPS;
}
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
- String filename = ("/sdcard/" + encoder + "_" + audio + "_" + quality + ".3gp");
+ String filename = ("/sdcard/" + videoEncoder + "_" + audioEncoder + "_" + highQuality + ".3gp");
try {
Log.v(TAG, "video encoder :" + videoEncoder);
Log.v(TAG, "audio encoder :" + audioEncoder);
- Log.v(TAG, "quality : " + quality);
- Log.v(TAG, "encoder : " + encoder);
- Log.v(TAG, "audio : " + audio);
+ Log.v(TAG, "quality : " + (highQuality?"high": "low"));
+ Log.v(TAG, "encoder : " + MediaProfileReader.getVideoCodecName(videoEncoder));
+ Log.v(TAG, "audio : " + MediaProfileReader.getAudioCodecName(audioEncoder));
Log.v(TAG, "videoWidth : " + videoWidth);
Log.v(TAG, "videoHeight : " + videoHeight);
Log.v(TAG, "videoFPS : " + videoFps);
@@ -434,35 +436,26 @@
boolean recordSuccess = false;
String deviceType = MediaProfileReader.getDeviceType();
Log.v(TAG, "deviceType = " + deviceType);
- // Test cases are device specified
- MediaProfileReader.createVideoProfileTable();
- MediaProfileReader.createAudioProfileTable();
- MediaProfileReader.createEncoderTable();
- String encoderType = MediaProfileReader.getVideoCodecProperty();
- String audioType = MediaProfileReader.getAudioCodecProperty();
- if ((encoderType.length() != 0) || (audioType.length() != 0)) {
- String audio[] = audioType.split(",");
- String encoder[] = encoderType.split(",");
- for (int k = 0; k < 2; k++) {
- for (int i = 0; i < encoder.length; i++) {
- for (int j = 0; j < audio.length; j++) {
- if (k == 0) {
- recordSuccess = recordVideoWithPara(encoder[i], audio[j], "high");
- } else {
- recordSuccess = recordVideoWithPara(encoder[i], audio[j], "low");
- }
- if (!recordSuccess) {
- Log.v(TAG, "testDeviceSpecificCodec failed");
- Log.v(TAG, "Encoder = " + encoder[i] + "Audio Encoder = " + audio[j]);
- noOfFailure++;
- }
- // assertTrue((encoder[i] + audio[j]), recordSuccess);
+ List<VideoEncoderCap> videoEncoders = MediaProfileReader.getVideoEncoders();
+ List<AudioEncoderCap> audioEncoders = MediaProfileReader.getAudioEncoders();
+ for (int k = 0; k < 2; k++) {
+ for (VideoEncoderCap videoEncoder: videoEncoders) {
+ for (AudioEncoderCap audioEncoder: audioEncoders) {
+ if (k == 0) {
+ recordSuccess = recordVideoWithPara(videoEncoder, audioEncoder, true);
+ } else {
+ recordSuccess = recordVideoWithPara(videoEncoder, audioEncoder, false);
+ }
+ if (!recordSuccess) {
+ Log.v(TAG, "testDeviceSpecificCodec failed");
+ Log.v(TAG, "Encoder = " + videoEncoder.mCodec + "Audio Encoder = " + audioEncoder.mCodec);
+ noOfFailure++;
}
}
}
- if (noOfFailure != 0) {
- assertTrue("testDeviceSpecificCodec", false);
- }
+ }
+ if (noOfFailure != 0) {
+ assertTrue("testDeviceSpecificCodec", false);
}
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
index 8750098..4c259f1 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
@@ -39,9 +39,8 @@
public static void testAlbumArt() throws Exception {
Log.v(TAG, "testAlbumArt starts.");
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- MediaProfileReader reader = new MediaProfileReader();
- boolean supportWMA = reader.getWMAEnable();
- boolean supportWMV = reader.getWMVEnable();
+ boolean supportWMA = MediaProfileReader.getWMAEnable();
+ boolean supportWMV = MediaProfileReader.getWMVEnable();
retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
for (int i = 0, n = MediaNames.ALBUMART_TEST_FILES.length; i < n; ++i) {
try {
@@ -74,9 +73,8 @@
@LargeTest
public static void testThumbnailCapture() throws Exception {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- MediaProfileReader reader = new MediaProfileReader();
- boolean supportWMA = reader.getWMAEnable();
- boolean supportWMV = reader.getWMVEnable();
+ boolean supportWMA = MediaProfileReader.getWMAEnable();
+ boolean supportWMV = MediaProfileReader.getWMVEnable();
Log.v(TAG, "Thumbnail processing starts");
long startedAt = System.currentTimeMillis();
for(int i = 0, n = MediaNames.THUMBNAIL_CAPTURE_TEST_FILES.length; i < n; ++i) {
@@ -110,9 +108,8 @@
@LargeTest
public static void testMetadataRetrieval() throws Exception {
- MediaProfileReader reader = new MediaProfileReader();
- boolean supportWMA = reader.getWMAEnable();
- boolean supportWMV = reader.getWMVEnable();
+ boolean supportWMA = MediaProfileReader.getWMAEnable();
+ boolean supportWMV = MediaProfileReader.getWMVEnable();
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
for(int i = 0, n = MediaNames.METADATA_RETRIEVAL_TEST_FILES.length; i < n; ++i) {
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 654ca32..a5a518b 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -61,12 +61,12 @@
<!-- user interface sound effects -->
<integer name="def_power_sounds_enabled">1</integer>
<string name="def_low_battery_sound">/system/media/ui/LowBattery.ogg</string>
- <integer name="def_dock_sounds_enabled">1</integer>
- <string name="def_desk_dock_sound">/system/media/audio/ui/dock.ogg</string>
- <string name="def_desk_undock_sound">/system/media/audio/ui/undock.ogg</string>
+ <integer name="def_dock_sounds_enabled">0</integer>
+ <string name="def_desk_dock_sound">/system/media/audio/ui/Dock.ogg</string>
+ <string name="def_desk_undock_sound">/system/media/audio/ui/Undock.ogg</string>
<string name="def_car_dock_sound">/system/media/audio/ui/Dock.ogg</string>
<string name="def_car_undock_sound">/system/media/audio/ui/Undock.ogg</string>
- <integer name="def_lockscreen_sounds_enabled">1</integer>
+ <integer name="def_lockscreen_sounds_enabled">0</integer>
<string name="def_lock_sound">/system/media/audio/ui/Lock.ogg</string>
<string name="def_unlock_sound">/system/media/audio/ui/Unlock.ogg</string>
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 958d089..7c555e2 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -256,14 +256,14 @@
Log.e(TAG, "Failed to parse netmask", uhe);
cfg.netmask = 0;
}
- cfg.interfaceFlags = st.nextToken("]");
+ cfg.interfaceFlags = st.nextToken("]").trim() +"]";
Log.d(TAG, String.format("flags <%s>", cfg.interfaceFlags));
return cfg;
}
public void setInterfaceConfig(
String iface, InterfaceConfiguration cfg) throws IllegalStateException {
- String cmd = String.format("interface setcfg %s %s %s", iface,
+ String cmd = String.format("interface setcfg %s %s %s %s", iface,
intToIpString(cfg.ipAddr), intToIpString(cfg.netmask), cfg.interfaceFlags);
mConnector.doCommand(cmd);
}
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 1d20074..10d6e3a 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -27,6 +27,7 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.ConnectivityManager;
+import android.net.InterfaceConfiguration;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.NetworkInfo;
@@ -56,6 +57,7 @@
*
* TODO - look for parent classes and code sharing
*/
+
public class Tethering extends INetworkManagementEventObserver.Stub {
private Notification mTetheringNotification;
@@ -80,6 +82,10 @@
private String mUpstreamIfaceName;
+ // turning on/off RNDIS resets the interface generating and extra discon/conn cycle
+ // count how many to ignore.. Self correcting if you plug/unplug a bunch of times.
+ private int mUsbResetExpected = 0;
+
HierarchicalStateMachine mTetherMasterSM;
public Tethering(Context context) {
@@ -113,7 +119,7 @@
com.android.internal.R.array.config_tether_dhcp_range);
if (mDhcpRange.length == 0) {
mDhcpRange = new String[2];
- mDhcpRange[0] = new String("169.254.2.1");
+ mDhcpRange[0] = new String("169.254.2.2");
mDhcpRange[1] = new String("169.254.2.64");
} else if(mDhcpRange.length == 1) {
String[] tmp = new String[2];
@@ -127,16 +133,6 @@
mTetherableWifiRegexs = context.getResources().getStringArray(
com.android.internal.R.array.config_tether_wifi_regexs);
- String[] ifaces = new String[0];
- try {
- ifaces = service.listInterfaces();
- } catch (Exception e) {
- Log.e(TAG, "Error listing Interfaces :" + e);
- }
- for (String iface : ifaces) {
- interfaceAdded(iface);
- }
-
// TODO - remove and rely on real notifications of the current iface
mDnsServers = new String[2];
mDnsServers[0] = "8.8.8.8";
@@ -147,6 +143,7 @@
public void interfaceLinkStatusChanged(String iface, boolean link) {
Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link);
boolean found = false;
+ boolean usb = false;
for (String regex : mTetherableWifiRegexs) {
if (iface.matches(regex)) {
found = true;
@@ -156,6 +153,7 @@
for (String regex: mTetherableUsbRegexs) {
if (iface.matches(regex)) {
found = true;
+ usb = true;
break;
}
}
@@ -165,7 +163,7 @@
TetherInterfaceSM sm = mIfaces.get(iface);
if (link) {
if (sm == null) {
- sm = new TetherInterfaceSM(iface);
+ sm = new TetherInterfaceSM(iface, usb);
mIfaces.put(iface, sm);
sm.start();
}
@@ -179,7 +177,10 @@
}
public void interfaceAdded(String iface) {
+ IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
boolean found = false;
+ boolean usb = false;
for (String regex : mTetherableWifiRegexs) {
if (iface.matches(regex)) {
found = true;
@@ -189,6 +190,7 @@
for (String regex : mTetherableUsbRegexs) {
if (iface.matches(regex)) {
found = true;
+ usb = true;
break;
}
}
@@ -196,13 +198,14 @@
Log.d(TAG, iface + " is not a tetherable iface, ignoring");
return;
}
+
synchronized (mIfaces) {
TetherInterfaceSM sm = mIfaces.get(iface);
if (sm != null) {
Log.e(TAG, "active iface (" + iface + ") reported as added, ignoring");
return;
}
- sm = new TetherInterfaceSM(iface);
+ sm = new TetherInterfaceSM(iface, usb);
mIfaces.put(iface, sm);
sm.start();
}
@@ -314,8 +317,8 @@
if (tellUser) {
for (Object o : availableList) {
String s = (String)o;
- for (Object matchObject : mTetherableUsbRegexs) {
- if (s.matches((String)matchObject)) {
+ for (String match : mTetherableUsbRegexs) {
+ if (s.matches(match)) {
showTetherAvailableNotification();
return;
}
@@ -414,20 +417,32 @@
}
}
-
-
-
private class StateReceiver extends BroadcastReceiver {
public void onReceive(Context content, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_UMS_CONNECTED)) {
- Tethering.this.handleTtyConnect();
+ Log.w(TAG, "got UMS connected");
+ synchronized (Tethering.this) {
+ if(mUsbResetExpected != 0) {
+ Log.w(TAG, "mUsbResetExpected == " + mUsbResetExpected + ", ignored");
+ mUsbResetExpected--;
+ return;
+ }
+ }
+ Tethering.this.toggleUsbIfaces(true); // add them
} else if (action.equals(Intent.ACTION_UMS_DISCONNECTED)) {
- Tethering.this.handleTtyDisconnect();
+ Log.w(TAG, "got UMS disconneded broadcast");
+ synchronized (Tethering.this) {
+ if(mUsbResetExpected != 0) {
+ Log.w(TAG, "mUsbResetExpected == " + mUsbResetExpected + ", ignored");
+ mUsbResetExpected--;
+ return;
+ }
+ }
+ Tethering.this.toggleUsbIfaces(false); // remove them
} else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
- IConnectivityManager service =
- IConnectivityManager.Stub.asInterface(b);
+ IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
try {
NetworkInfo info = service.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_DUN);
int msg;
@@ -442,6 +457,114 @@
}
}
+ // used on cable insert/remove
+ private void toggleUsbIfaces(boolean add) {
+ IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
+ String[] ifaces = new String[0];
+ try {
+ ifaces = service.listInterfaces();
+ } catch (Exception e) {
+ Log.e(TAG, "Error listing Interfaces :" + e);
+ return;
+ }
+ for (String iface : ifaces) {
+ for (String regex : mTetherableUsbRegexs) {
+ if (iface.matches(regex)) {
+ if (add) {
+ interfaceAdded(iface);
+ } else {
+ interfaceRemoved(iface);
+ }
+ }
+ }
+ }
+ }
+
+ // toggled when we enter/leave the fully teathered state
+ private boolean enableRndisUsb(boolean enabled) {
+ Log.d(TAG, "enableRndisUsb(" + enabled + ")");
+ IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
+
+ try {
+ if (enabled) {
+ // turning this on will reset USB and generate two bogus events - ignore them
+ synchronized (this) {
+ if (!service.isUsbRNDISStarted()) {
+ mUsbResetExpected += 2;
+ service.startUsbRNDIS();
+ }
+ }
+ } else {
+ if (service.isUsbRNDISStarted()) {
+ service.stopUsbRNDIS();
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error toggling usb RNDIS :" + e);
+ return false;
+ }
+ return true;
+ }
+
+ // configured when we start tethering and unconfig'd on error or conclusion
+ private boolean configureUsb(boolean enabled) {
+ Log.d(TAG, "configureUsb(" + enabled + ")");
+
+ IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
+
+ // bring toggle the interfaces
+ String[] ifaces = new String[0];
+ try {
+ ifaces = service.listInterfaces();
+ } catch (Exception e) {
+ Log.e(TAG, "Error listing Interfaces :" + e);
+ return false;
+ }
+ for (String iface : ifaces) {
+ for (String regex : mTetherableUsbRegexs) {
+ if (iface.matches(regex)) {
+ InterfaceConfiguration ifcg = null;
+ try {
+ ifcg = service.getInterfaceConfig(iface);
+ if (ifcg != null) {
+ ifcg.ipAddr = (169 << 24) + (254 << 16) + (2 << 8) + 1;
+ ifcg.netmask = (255 << 24) + (255 << 16) + (255 << 8) + 0;
+ if (enabled) {
+ ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
+ } else {
+ ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
+ }
+ service.setInterfaceConfig(iface, ifcg);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
+ return false;
+ }
+ }
+ }
+ }
+
+ if (!enabled) {
+ // turn off ndis
+ try {
+ synchronized (this) {
+ if (service.isUsbRNDISStarted()) {
+ mUsbResetExpected += 2;
+ service.stopUsbRNDIS();
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error stopping usb RNDIS :" + e);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
private void handleTtyConnect() {
Log.d(TAG, "handleTtyConnect");
// for each of the available Tty not already supported by a ppp session,
@@ -609,6 +732,7 @@
private HierarchicalState mUntetherInterfaceErrorState;
private HierarchicalState mEnableNatErrorState;
private HierarchicalState mDisableNatErrorState;
+ private HierarchicalState mUsbConfigurationErrorState;
private HierarchicalState mUnavailableState;
@@ -617,10 +741,12 @@
private boolean mTethered;
String mIfaceName;
+ boolean mUsb;
- TetherInterfaceSM(String name) {
+ TetherInterfaceSM(String name, boolean usb) {
super(name);
mIfaceName = name;
+ mUsb = usb;
mInitialState = new InitialState();
addState(mInitialState);
@@ -638,6 +764,8 @@
addState(mEnableNatErrorState);
mDisableNatErrorState = new DisableNatErrorState();
addState(mDisableNatErrorState);
+ mUsbConfigurationErrorState = new UsbConfigurationErrorState();
+ addState(mUsbConfigurationErrorState);
mUnavailableState = new UnavailableState();
addState(mUnavailableState);
@@ -656,6 +784,7 @@
if (current == mUntetherInterfaceErrorState) res += "UntetherInterfaceErrorState";
if (current == mEnableNatErrorState) res += "EnableNatErrorState";
if (current == mDisableNatErrorState) res += "DisableNatErrorState";
+ if (current == mUsbConfigurationErrorState) res += "UsbConfigurationErrorState";
if (current == mUnavailableState) res += "UnavailableState";
if (mAvailable) res += " - Available";
if (mTethered) res += " - Tethered";
@@ -686,8 +815,15 @@
return mErrored;
}
- private synchronized void setErrored(boolean errored) {
- mErrored = errored;
+ private void setErrored(boolean errored) {
+ synchronized (this) {
+ mErrored = errored;
+ }
+ if (errored && mUsb) {
+ // note everything's been unwound by this point so nothing to do on
+ // further error..
+ Tethering.this.configureUsb(false);
+ }
}
class InitialState extends HierarchicalState {
@@ -726,6 +862,19 @@
@Override
public void enter() {
setAvailable(false);
+ if (mUsb) {
+ if (!Tethering.this.configureUsb(true)) {
+ Message m = mTetherMasterSM.obtainMessage(
+ TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED);
+ m.obj = TetherInterfaceSM.this;
+ mTetherMasterSM.sendMessage(m);
+
+ m = obtainMessage(CMD_TRANSITION_TO_ERROR);
+ m.obj = mUsbConfigurationErrorState;
+ sendMessageAtFrontOfQueue(m);
+ return;
+ }
+ }
sendTetherStateChangedBroadcast();
}
@Override
@@ -739,6 +888,12 @@
TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED);
m.obj = TetherInterfaceSM.this;
mTetherMasterSM.sendMessage(m);
+ if (mUsb) {
+ if (!Tethering.this.configureUsb(false)) {
+ transitionTo(mUsbConfigurationErrorState);
+ break;
+ }
+ }
transitionTo(mInitialState);
break;
case CMD_TETHER_MODE_ALIVE:
@@ -759,6 +914,10 @@
mTetherMasterSM.sendMessage(m);
transitionTo(mUnavailableState);
break;
+ case CMD_TRANSITION_TO_ERROR:
+ HierarchicalState s = (HierarchicalState)(message.obj);
+ transitionTo(s);
+ break;
default:
retValue = false;
}
@@ -788,12 +947,17 @@
sendMessageAtFrontOfQueue(m);
return;
}
+ if (mUsb) Tethering.this.enableRndisUsb(true);
Log.d(TAG, "Tethered " + mIfaceName);
setAvailable(false);
setTethered(true);
sendTetherStateChangedBroadcast();
}
@Override
+ public void exit() {
+ if(mUsb) Tethering.this.enableRndisUsb(false);
+ }
+ @Override
public boolean processMessage(Message message) {
Log.d(TAG, "TetheredState.processMessage what=" + message.what);
boolean retValue = true;
@@ -821,7 +985,15 @@
m.obj = TetherInterfaceSM.this;
mTetherMasterSM.sendMessage(m);
if (message.what == CMD_TETHER_UNREQUESTED) {
- transitionTo(mInitialState);
+ if (mUsb) {
+ if (!Tethering.this.configureUsb(false)) {
+ transitionTo(mUsbConfigurationErrorState);
+ } else {
+ transitionTo(mInitialState);
+ }
+ } else {
+ transitionTo(mInitialState);
+ }
} else if (message.what == CMD_INTERFACE_DOWN) {
transitionTo(mUnavailableState);
}
@@ -857,6 +1029,12 @@
}
Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
sendTetherStateChangedBroadcast();
+ if (mUsb) {
+ if (!Tethering.this.configureUsb(false)) {
+ transitionTo(mUsbConfigurationErrorState);
+ break;
+ }
+ }
transitionTo(mInitialState);
break;
case CMD_TRANSITION_TO_ERROR:
@@ -974,6 +1152,15 @@
sendTetherStateChangedBroadcast();
}
}
+
+ class UsbConfigurationErrorState extends ErrorState {
+ @Override
+ public void enter() {
+ Log.e(TAG, "Error trying to configure USB " + mIfaceName);
+ setAvailable(false);
+ setErrored(true);
+ }
+ }
}
class TetherMasterSM extends HierarchicalStateMachine {
@@ -1179,6 +1366,7 @@
class CellDunAliveState extends HierarchicalState {
@Override
public void enter() {
+ Log.d(TAG, "renewing Dun in " + CELL_DUN_RENEW_MS + "ms");
sendMessageDelayed(obtainMessage(CMD_CELL_DUN_RENEW), CELL_DUN_RENEW_MS);
}
@@ -1228,6 +1416,8 @@
transitionTo(mInitialState);
break;
case CMD_CELL_DUN_RENEW:
+ Log.d(TAG, "renewing dun connection - requeuing for another " +
+ CELL_DUN_RENEW_MS + "ms");
b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
IConnectivityManager cservice = IConnectivityManager.Stub.asInterface(b);
try {
@@ -1248,6 +1438,8 @@
class TetherModeAliveState extends HierarchicalState {
@Override
public void enter() {
+ Log.d(TAG, "renewing Dun in " + CELL_DUN_RENEW_MS + "ms");
+ sendMessageDelayed(obtainMessage(CMD_CELL_DUN_RENEW), CELL_DUN_RENEW_MS);
for (Object o : mNotifyList) {
TetherInterfaceSM sm = (TetherInterfaceSM)o;
sm.sendMessage(sm.obtainMessage(TetherInterfaceSM.CMD_TETHER_MODE_ALIVE));
@@ -1298,6 +1490,18 @@
}
transitionTo(mInitialState);
break;
+ case CMD_CELL_DUN_RENEW:
+ Log.d(TAG, "renewing dun connection - requeuing for another " +
+ CELL_DUN_RENEW_MS + "ms");
+ b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
+ IConnectivityManager cservice = IConnectivityManager.Stub.asInterface(b);
+ try {
+ cservice.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
+ Phone.FEATURE_ENABLE_DUN, new Binder());
+ } catch (Exception e) {
+ }
+ sendMessageDelayed(obtainMessage(CMD_CELL_DUN_RENEW), CELL_DUN_RENEW_MS);
+ break;
default:
retValue = false;
break;
diff --git a/services/java/com/android/server/status/ExpandedView.java b/services/java/com/android/server/status/ExpandedView.java
index d0f14cb..33ac8c1 100644
--- a/services/java/com/android/server/status/ExpandedView.java
+++ b/services/java/com/android/server/status/ExpandedView.java
@@ -11,17 +11,11 @@
public class ExpandedView extends LinearLayout {
- final Display mDisplay;
StatusBarService mService;
- boolean mTracking;
- int mStartX, mStartY;
- int mMaxHeight = 0;
int mPrevHeight = -1;
public ExpandedView(Context context, AttributeSet attrs) {
super(context, attrs);
- mDisplay = ((WindowManager)context.getSystemService(
- Context.WINDOW_SERVICE)).getDefaultDisplay();
}
@Override
@@ -36,12 +30,6 @@
}
@Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec,
- MeasureSpec.makeMeasureSpec(mMaxHeight, MeasureSpec.AT_MOST));
- }
-
- @Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
int height = bottom - top;
@@ -51,11 +39,4 @@
mService.updateExpandedViewPos(StatusBarService.EXPANDED_LEAVE_ALONE);
}
}
-
- void setMaxHeight(int h) {
- if (h != mMaxHeight) {
- mMaxHeight = h;
- requestLayout();
- }
- }
}
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 493bd93..3f77291 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -187,8 +187,9 @@
TextView mSpnLabel;
TextView mPlmnLabel;
TextView mClearButton;
+ View mExpandedContents;
CloseDragHandle mCloseView;
- int[] mCloseLocation = new int[2];
+ int[] mPositionTmp = new int[2];
boolean mExpanded;
boolean mExpandedVisible;
@@ -198,7 +199,7 @@
// the tracker view
TrackingView mTrackingView;
WindowManager.LayoutParams mTrackingParams;
- int mTrackingPosition;
+ int mTrackingPosition; // the position of the top of the tracking view.
// ticker
private Ticker mTicker;
@@ -274,6 +275,7 @@
mExpandedDialog = new ExpandedDialog(context);
mExpandedView = expanded;
+ mExpandedContents = expanded.findViewById(R.id.notificationLinearLayout);
mOngoingTitle = (TextView)expanded.findViewById(R.id.ongoingTitle);
mOngoingItems = (LinearLayout)expanded.findViewById(R.id.ongoingItems);
mLatestTitle = (TextView)expanded.findViewById(R.id.latestTitle);
@@ -1530,20 +1532,11 @@
/// ---------- Expanded View --------------
pixelFormat = PixelFormat.TRANSLUCENT;
- bg = mExpandedView.getBackground();
- if (bg != null) {
- pixelFormat = bg.getOpacity();
- if (pixelFormat != PixelFormat.TRANSLUCENT) {
- // we want good-looking gradients, so we force a 8-bits per
- // pixel format.
- pixelFormat = PixelFormat.RGBX_8888;
- }
- }
final int disph = mDisplay.getHeight();
lp = mExpandedDialog.getWindow().getAttributes();
lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
- lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ lp.height = getExpandedHeight();
lp.x = 0;
mTrackingPosition = lp.y = -disph; // sufficiently large negative
lp.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
@@ -1562,10 +1555,10 @@
mExpandedDialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
mExpandedDialog.setContentView(mExpandedView,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ mExpandedDialog.getWindow().setBackgroundDrawable(null);
mExpandedDialog.show();
FrameLayout hack = (FrameLayout)mExpandedView.getParent();
- hack.setForeground(null);
}
void setDateViewVisibility(boolean visible, int anim) {
@@ -1630,11 +1623,15 @@
mTrackingParams.height = disph-h;
WindowManagerImpl.getDefault().updateViewLayout(mTrackingView, mTrackingParams);
- mCloseView.getLocationInWindow(mCloseLocation);
-
if (mExpandedParams != null) {
+ mCloseView.getLocationInWindow(mPositionTmp);
+ final int closePos = mPositionTmp[1];
+
+ mExpandedContents.getLocationInWindow(mPositionTmp);
+ final int contentsBottom = mPositionTmp[1] + mExpandedContents.getHeight();
+
mExpandedParams.y = pos + mTrackingView.getHeight()
- - (mTrackingParams.height-mCloseLocation[1]) - mExpandedView.getHeight();
+ - (mTrackingParams.height-closePos) - contentsBottom;
int max = h;
if (mExpandedParams.y > max) {
mExpandedParams.y = max;
@@ -1644,13 +1641,13 @@
mExpandedParams.y = min;
}
- /*
- Log.d(TAG, "mTrackingPosition=" + mTrackingPosition
- + " mTrackingView.height=" + mTrackingView.getHeight()
- + " diff=" + (mTrackingPosition + mTrackingView.getHeight())
- + " h=" + h);
- */
- panelSlightlyVisible((mTrackingPosition + mTrackingView.getHeight()) > h);
+ boolean visible = (mTrackingPosition + mTrackingView.getHeight()) > h;
+ if (!visible) {
+ // if the contents aren't visible, move the expanded view way off screen
+ // because the window itself extends below the content view.
+ mExpandedParams.y = -disph;
+ }
+ panelSlightlyVisible(visible);
mExpandedDialog.getWindow().setAttributes(mExpandedParams);
}
@@ -1658,16 +1655,19 @@
Log.d(TAG, "updateExpandedViewPos after expandedPosition=" + expandedPosition
+ " mTrackingParams.y=" + mTrackingParams.y
+ " mTrackingPosition=" + mTrackingPosition
- + " mExpandedParams.y=" + mExpandedParams.y);
+ + " mExpandedParams.y=" + mExpandedParams.y
+ + " mExpandedParams.height=" + mExpandedParams.height);
}
}
- void updateAvailableHeight() {
+ int getExpandedHeight() {
+ return mDisplay.getHeight() - mStatusBarView.getHeight() - mCloseView.getHeight();
+ }
+
+ void updateExpandedHeight() {
if (mExpandedView != null) {
- int disph = mDisplay.getHeight();
- int h = mStatusBarView.getHeight();
- int max = disph - (mCloseView.getHeight() + h);
- mExpandedView.setMaxHeight(max);
+ mExpandedParams.height = getExpandedHeight();
+ mExpandedDialog.getWindow().setAttributes(mExpandedParams);
}
}
diff --git a/services/java/com/android/server/status/TrackingView.java b/services/java/com/android/server/status/TrackingView.java
index 722d10c..886d66d 100644
--- a/services/java/com/android/server/status/TrackingView.java
+++ b/services/java/com/android/server/status/TrackingView.java
@@ -23,7 +23,7 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- mService.updateAvailableHeight();
+ mService.updateExpandedHeight();
}
@Override
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 52c8b1f..cab7b81 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -440,10 +440,11 @@
return Phone.APN_REQUEST_FAILED;
}
- if(DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = "
+ if (DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = "
+ isApnTypeActive(type) + " and state = " + state);
if (!isApnTypeAvailable(type)) {
+ if (DBG) Log.d(LOG_TAG, "type not available");
return Phone.APN_TYPE_NOT_AVAILABLE;
}
diff --git a/tests/CoreTests/android/core/MiscRegressionTest.java b/tests/CoreTests/android/core/MiscRegressionTest.java
index 8fe064c..8281db0 100644
--- a/tests/CoreTests/android/core/MiscRegressionTest.java
+++ b/tests/CoreTests/android/core/MiscRegressionTest.java
@@ -110,6 +110,16 @@
Logger.global.finest("This has logging Level.FINEST, should become VERBOSE");
}
+ // Regression test for Issue 5697:
+ // getContextClassLoader returns a non-application classloader
+ // http://code.google.com/p/android/issues/detail?id=5697
+ //
+ @MediumTest
+ public void testJavaContextClassLoader() throws Exception {
+ Assert.assertNotNull("Must hava a Java context ClassLoader",
+ Thread.currentThread().getContextClassLoader());
+ }
+
// Regression test for #1045939: Different output for Method.toString()
@SmallTest
public void testMethodToString() {
diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp
index 51afc0a..a09cec0 100644
--- a/tools/aapt/StringPool.cpp
+++ b/tools/aapt/StringPool.cpp
@@ -25,8 +25,12 @@
const size_t NS = pool->size();
for (size_t s=0; s<NS; s++) {
size_t len;
- printf("String #%ld: %s\n", s,
- String8(pool->stringAt(s, &len)).string());
+ const char *str = (const char*)pool->string8At(s, &len);
+ if (str == NULL) {
+ str = String8(pool->stringAt(s, &len)).string();
+ }
+
+ printf("String #%ld: %s\n", s, str);
}
}
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index afaed24..810e4d2 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -943,7 +943,7 @@
} else {
newDetailedState = DetailedState.FAILED;
}
- handleDisconnectedState(newDetailedState);
+ handleDisconnectedState(newDetailedState, true);
/**
* If we were associated with a network (networkId != -1),
* assume we reached this state because of a failed attempt
@@ -965,7 +965,7 @@
} else if (newState == SupplicantState.DISCONNECTED) {
mHaveIpAddress = false;
if (isDriverStopped() || mDisconnectExpected) {
- handleDisconnectedState(DetailedState.DISCONNECTED);
+ handleDisconnectedState(DetailedState.DISCONNECTED, true);
} else {
scheduleDisconnect();
}
@@ -1072,16 +1072,10 @@
*/
if (wasDisconnectPending) {
DetailedState saveState = getNetworkInfo().getDetailedState();
- handleDisconnectedState(DetailedState.DISCONNECTED);
+ handleDisconnectedState(DetailedState.DISCONNECTED, false);
setDetailedStateInternal(saveState);
- } else {
- /**
- * stop DHCP to ensure there is a new IP address
- * even if the supplicant transitions without disconnect
- * COMPLETED -> ASSOCIATED -> COMPLETED
- */
- resetConnections(false);
}
+
configureInterface();
mLastBssid = result.BSSID;
mLastSsid = mWifiInfo.getSSID();
@@ -1116,7 +1110,7 @@
case EVENT_DEFERRED_DISCONNECT:
if (mWifiInfo.getSupplicantState() != SupplicantState.UNINITIALIZED) {
- handleDisconnectedState(DetailedState.DISCONNECTED);
+ handleDisconnectedState(DetailedState.DISCONNECTED, true);
}
break;
@@ -1284,13 +1278,15 @@
* Reset our IP state and send out broadcasts following a disconnect.
* @param newState the {@code DetailedState} to set. Should be either
* {@code DISCONNECTED} or {@code FAILED}.
+ * @param disableInterface indicates whether the interface should
+ * be disabled
*/
- private void handleDisconnectedState(DetailedState newState) {
+ private void handleDisconnectedState(DetailedState newState, boolean disableInterface) {
if (mDisconnectPending) {
cancelDisconnect();
}
mDisconnectExpected = false;
- resetConnections(true);
+ resetConnections(disableInterface);
setDetailedState(newState);
sendNetworkStateChangeBroadcast(mLastBssid);
mWifiInfo.setBSSID(null);