diff options
82 files changed, 2108 insertions, 875 deletions
@@ -120,6 +120,7 @@ LOCAL_SRC_FILES += \ core/java/android/os/IMessenger.aidl \ core/java/android/os/storage/IMountService.aidl \ core/java/android/os/storage/IMountServiceListener.aidl \ + core/java/android/os/storage/IMountShutdownObserver.aidl \ core/java/android/os/INetworkManagementService.aidl \ core/java/android/os/INetStatService.aidl \ core/java/android/os/IPermissionController.aidl \ diff --git a/api/current.xml b/api/current.xml index 21c1c18..c2d273d 100644 --- a/api/current.xml +++ b/api/current.xml @@ -174601,6 +174601,19 @@ visibility="public" > </method> +<method name="getXVelocity" + return="float" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="id" type="int"> +</parameter> +</method> <method name="getYVelocity" return="float" abstract="false" @@ -174612,6 +174625,19 @@ visibility="public" > </method> +<method name="getYVelocity" + return="float" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="id" type="int"> +</parameter> +</method> <method name="obtain" return="android.view.VelocityTracker" abstract="false" @@ -179390,6 +179416,17 @@ visibility="public" > </method> +<method name="getScaledPagingTouchSlop" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getScaledScrollBarSize" return="int" abstract="false" @@ -193450,6 +193487,17 @@ visibility="public" > </method> +<method name="getUseSystemOverscrollBackground" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getUseWideViewPort" return="boolean" abstract="false" @@ -194029,6 +194077,19 @@ <parameter name="use" type="boolean"> </parameter> </method> +<method name="setUseSystemOverscrollBackground" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="system" type="boolean"> +</parameter> +</method> <method name="setUseWideViewPort" return="void" abstract="false" diff --git a/cmds/servicemanager/Android.mk b/cmds/servicemanager/Android.mk index 25266a2..fe5929b 100644 --- a/cmds/servicemanager/Android.mk +++ b/cmds/servicemanager/Android.mk @@ -10,5 +10,8 @@ include $(CLEAR_VARS) LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := service_manager.c binder.c LOCAL_MODULE := servicemanager +ifeq ($(BOARD_USE_LVMX),true) + LOCAL_CFLAGS += -DLVMX +endif include $(BUILD_EXECUTABLE) endif diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c index f3a4713..a2006c1 100644 --- a/cmds/servicemanager/service_manager.c +++ b/cmds/servicemanager/service_manager.c @@ -27,6 +27,9 @@ static struct { unsigned uid; const char *name; } allowed[] = { +#ifdef LVMX + { AID_MEDIA, "com.lifevibes.mx.ipc" }, +#endif { AID_MEDIA, "media.audio_flinger" }, { AID_MEDIA, "media.player" }, { AID_MEDIA, "media.camera" }, diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index 3e426f5..bf9b021 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -668,7 +668,10 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // The user changed the query, remember it. mUserQuery = s == null ? "" : s.toString(); } - updateVoiceButton(mSearchAutoComplete.isEmpty()); + // Always want to show the microphone if the context is voice. + updateVoiceButton(mSearchAutoComplete.isEmpty() + || (mAppSearchData != null && mAppSearchData.getBoolean( + SearchManager.CONTEXT_IS_VOICE))); } public void afterTextChanged(Editable s) { diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index 0ed572a..625b120 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -1544,6 +1544,15 @@ public class SearchManager public final static String INTENT_ACTION_NONE = "android.search.action.ZILCH"; /** + * This means that context is voice, and therefore the SearchDialog should + * continue showing the microphone until the user indicates that he/she does + * not want to re-speak (e.g. by typing). + * + * @hide + */ + public final static String CONTEXT_IS_VOICE = "android.search.CONTEXT_IS_VOICE"; + + /** * Reference to the shared system search service. */ private static ISearchManager mService; diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java index de52e65..fdb3d20 100644 --- a/core/java/android/content/ContentProviderNative.java +++ b/core/java/android/content/ContentProviderNative.java @@ -73,7 +73,10 @@ abstract public class ContentProviderNative extends Binder implements IContentPr case QUERY_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); + Uri url = Uri.CREATOR.createFromParcel(data); + + // String[] projection int num = data.readInt(); String[] projection = null; if (num > 0) { @@ -82,6 +85,8 @@ abstract public class ContentProviderNative extends Binder implements IContentPr projection[i] = data.readString(); } } + + // String selection, String[] selectionArgs... String selection = data.readString(); num = data.readInt(); String[] selectionArgs = null; @@ -91,19 +96,33 @@ abstract public class ContentProviderNative extends Binder implements IContentPr selectionArgs[i] = data.readString(); } } + String sortOrder = data.readString(); IContentObserver observer = IContentObserver.Stub. asInterface(data.readStrongBinder()); CursorWindow window = CursorWindow.CREATOR.createFromParcel(data); + // Flag for whether caller wants the number of + // rows in the cursor and the position of the + // "_id" column index (or -1 if non-existent) + // Only to be returned if binder != null. + boolean wantsCursorMetadata = data.readInt() != 0; + IBulkCursor bulkCursor = bulkQuery(url, projection, selection, selectionArgs, sortOrder, observer, window); reply.writeNoException(); if (bulkCursor != null) { reply.writeStrongBinder(bulkCursor.asBinder()); + + if (wantsCursorMetadata) { + reply.writeInt(bulkCursor.count()); + reply.writeInt(BulkCursorToCursorAdaptor.findRowIdColumnIndex( + bulkCursor.getColumnNames())); + } } else { reply.writeStrongBinder(null); } + return true; } @@ -266,9 +285,12 @@ final class ContentProviderProxy implements IContentProvider return mRemote; } - public IBulkCursor bulkQuery(Uri url, String[] projection, - String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, - CursorWindow window) throws RemoteException { + // Like bulkQuery() but sets up provided 'adaptor' if not null. + private IBulkCursor bulkQueryInternal( + Uri url, String[] projection, + String selection, String[] selectionArgs, String sortOrder, + IContentObserver observer, CursorWindow window, + BulkCursorToCursorAdaptor adaptor) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -297,6 +319,12 @@ final class ContentProviderProxy implements IContentProvider data.writeStrongBinder(observer.asBinder()); window.writeToParcel(data, 0); + // Flag for whether or not we want the number of rows in the + // cursor and the position of the "_id" column index (or -1 if + // non-existent). Only to be returned if binder != null. + final boolean wantsCursorMetadata = (adaptor != null); + data.writeInt(wantsCursorMetadata ? 1 : 0); + mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0); DatabaseUtils.readExceptionFromParcel(reply); @@ -305,26 +333,43 @@ final class ContentProviderProxy implements IContentProvider IBinder bulkCursorBinder = reply.readStrongBinder(); if (bulkCursorBinder != null) { bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder); + + if (wantsCursorMetadata) { + int rowCount = reply.readInt(); + int idColumnPosition = reply.readInt(); + if (bulkCursor != null) { + adaptor.set(bulkCursor, rowCount, idColumnPosition); + } + } } - + data.recycle(); reply.recycle(); - + return bulkCursor; } + public IBulkCursor bulkQuery(Uri url, String[] projection, + String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, + CursorWindow window) throws RemoteException { + return bulkQueryInternal( + url, projection, selection, selectionArgs, sortOrder, + observer, window, + null /* BulkCursorToCursorAdaptor */); + } + public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws RemoteException { //TODO make a pool of windows so we can reuse memory dealers CursorWindow window = new CursorWindow(false /* window will be used remotely */); BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor(); - IBulkCursor bulkCursor = bulkQuery(url, projection, selection, selectionArgs, sortOrder, - adaptor.getObserver(), window); - + IBulkCursor bulkCursor = bulkQueryInternal( + url, projection, selection, selectionArgs, sortOrder, + adaptor.getObserver(), window, + adaptor); if (bulkCursor == null) { return null; } - adaptor.set(bulkCursor); return adaptor; } diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 8773f59..423f4bc 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -237,7 +237,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * * {@hide} */ - public static final int FLAG_ON_SDCARD = 1<<20; + public static final int FLAG_EXTERNAL_STORAGE = 1<<20; /** * Value for {@link #flags}: Set to true if the application is diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 5da7fd1..9736b01 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -755,14 +755,14 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifest); pkg.mVersionCode = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_versionCode, 0); - pkg.mVersionName = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifest_versionName); + pkg.mVersionName = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifest_versionName, 0); if (pkg.mVersionName != null) { pkg.mVersionName = pkg.mVersionName.intern(); } - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifest_sharedUserId); - if (str != null) { + String str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0); + if (str != null && str.length() > 0) { String nameError = validateName(str, true); if (nameError != null && !"android".equals(pkgName)) { outError[0] = "<manifest> specifies bad sharedUserId name \"" @@ -828,6 +828,8 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestUsesPermission); + // Note: don't allow this value to be a reference to a resource + // that may change. String name = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestUsesPermission_name); @@ -871,6 +873,8 @@ public class PackageParser { FeatureInfo fi = new FeatureInfo(); sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestUsesFeature); + // Note: don't allow this value to be a reference to a resource + // that may change. fi.name = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestUsesFeature_name); if (fi.name == null) { @@ -1002,6 +1006,8 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestProtectedBroadcast); + // Note: don't allow this value to be a reference to a resource + // that may change. String name = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name); @@ -1027,8 +1033,8 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestOriginalPackage); - String orig =sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestOriginalPackage_name); + String orig =sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0); if (!pkg.packageName.equals(orig)) { if (pkg.mOriginalPackages == null) { pkg.mOriginalPackages = new ArrayList<String>(); @@ -1045,8 +1051,8 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestOriginalPackage); - String name = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestOriginalPackage_name); + String name = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0); sa.recycle(); @@ -1271,6 +1277,8 @@ public class PackageParser { return null; } + // Note: don't allow this value to be a reference to a resource + // that may change. perm.info.group = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup); if (perm.info.group != null) { @@ -1375,6 +1383,8 @@ public class PackageParser { } String str; + // Note: don't allow this value to be a reference to a resource + // that may change. str = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage); a.info.targetPackage = str != null ? str.intern() : null; @@ -1415,8 +1425,8 @@ public class PackageParser { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestApplication); - String name = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_name); + String name = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestApplication_name, 0); if (name != null) { ai.className = buildClassName(pkgName, name, outError); if (ai.className == null) { @@ -1426,8 +1436,8 @@ public class PackageParser { } } - String manageSpaceActivity = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity); + String manageSpaceActivity = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity, 0); if (manageSpaceActivity != null) { ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity, outError); @@ -1440,8 +1450,8 @@ public class PackageParser { // backupAgent, killAfterRestore, restoreNeedsApplication, and restoreAnyVersion // are only relevant if backup is possible for the given application. - String backupAgent = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_backupAgent); + String backupAgent = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestApplication_backupAgent, 0); if (backupAgent != null) { ai.backupAgentName = buildClassName(pkgName, backupAgent, outError); if (false) { @@ -1493,7 +1503,7 @@ public class PackageParser { } if ((flags & PARSE_ON_SDCARD) != 0) { - ai.flags |= ApplicationInfo.FLAG_ON_SDCARD; + ai.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE; } if (sa.getBoolean( @@ -1539,21 +1549,22 @@ public class PackageParser { } String str; - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_permission); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestApplication_permission, 0); ai.permission = (str != null && str.length() > 0) ? str.intern() : null; - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity, 0); ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName, str, outError); if (outError[0] == null) { - ai.processName = buildProcessName(ai.packageName, null, sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_process), + ai.processName = buildProcessName(ai.packageName, null, sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestApplication_process, 0), flags, mSeparateProcesses, outError); - ai.enabled = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_enabled, true); + ai.enabled = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_enabled, true); } sa.recycle(); @@ -1632,6 +1643,8 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestUsesLibrary); + // Note: don't allow this value to be a reference to a resource + // that may change. String lname = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestUsesLibrary_name); boolean req = sa.getBoolean( @@ -1681,7 +1694,7 @@ public class PackageParser { private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo, String[] outError, String tag, TypedArray sa, int nameRes, int labelRes, int iconRes) { - String name = sa.getNonResourceString(nameRes); + String name = sa.getNonConfigurationString(nameRes, 0); if (name == null) { outError[0] = tag + " does not specify android:name"; return false; @@ -1747,16 +1760,16 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestActivity_theme, 0); String str; - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestActivity_permission); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestActivity_permission, 0); if (str == null) { a.info.permission = owner.applicationInfo.permission; } else { a.info.permission = str.length() > 0 ? str.toString().intern() : null; } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity, 0); a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName, owner.applicationInfo.taskAffinity, str, outError); @@ -1902,8 +1915,8 @@ public class PackageParser { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestActivityAlias); - String targetActivity = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity); + String targetActivity = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity, 0); if (targetActivity == null) { outError[0] = "<activity-alias> does not specify android:targetActivity"; sa.recycle(); @@ -1980,8 +1993,8 @@ public class PackageParser { } String str; - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestActivityAlias_permission); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0); if (str != null) { a.info.permission = str.length() > 0 ? str.toString().intern() : null; } @@ -2068,17 +2081,17 @@ public class PackageParser { p.info.exported = sa.getBoolean( com.android.internal.R.styleable.AndroidManifestProvider_exported, true); - String cpname = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestProvider_authorities); + String cpname = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0); p.info.isSyncable = sa.getBoolean( com.android.internal.R.styleable.AndroidManifestProvider_syncable, false); - String permission = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestProvider_permission); - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestProvider_readPermission); + String permission = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestProvider_permission, 0); + String str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0); if (str == null) { str = permission; } @@ -2088,8 +2101,8 @@ public class PackageParser { p.info.readPermission = str.length() > 0 ? str.toString().intern() : null; } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestProvider_writePermission); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0); if (str == null) { str = permission; } @@ -2152,20 +2165,20 @@ public class PackageParser { PatternMatcher pa = null; - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path); + String str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0); if (str != null) { pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL); } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0); if (str != null) { pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX); } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0); if (str != null) { pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB); } @@ -2203,15 +2216,15 @@ public class PackageParser { PathPermission pa = null; - String permission = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPathPermission_permission); - String readPermission = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission); + String permission = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0); + String readPermission = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0); if (readPermission == null) { readPermission = permission; } - String writePermission = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission); + String writePermission = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0); if (writePermission == null) { writePermission = permission; } @@ -2238,22 +2251,22 @@ public class PackageParser { return false; } - String path = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPathPermission_path); + String path = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0); if (path != null) { pa = new PathPermission(path, PatternMatcher.PATTERN_LITERAL, readPermission, writePermission); } - path = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix); + path = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0); if (path != null) { pa = new PathPermission(path, PatternMatcher.PATTERN_PREFIX, readPermission, writePermission); } - path = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern); + path = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0); if (path != null) { pa = new PathPermission(path, PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission); @@ -2335,8 +2348,8 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestService_exported, false); } - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestService_permission); + String str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestService_permission, 0); if (str == null) { s.info.permission = owner.applicationInfo.permission; } else { @@ -2433,8 +2446,8 @@ public class PackageParser { data = new Bundle(); } - String name = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestMetaData_name); + String name = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestMetaData_name, 0); if (name == null) { outError[0] = "<meta-data> requires an android:name attribute"; sa.recycle(); @@ -2552,8 +2565,8 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestData); - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_mimeType); + String str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_mimeType, 0); if (str != null) { try { outInfo.addDataType(str); @@ -2564,34 +2577,34 @@ public class PackageParser { } } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_scheme); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_scheme, 0); if (str != null) { outInfo.addDataScheme(str); } - String host = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_host); - String port = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_port); + String host = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_host, 0); + String port = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_port, 0); if (host != null) { outInfo.addDataAuthority(host, port); } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_path); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_path, 0); if (str != null) { outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL); } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_pathPrefix); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0); if (str != null) { outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX); } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_pathPattern); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0); if (str != null) { outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB); } @@ -2754,7 +2767,7 @@ public class PackageParser { public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) { owner = args.owner; intents = new ArrayList<II>(0); - String name = args.sa.getNonResourceString(args.nameRes); + String name = args.sa.getNonConfigurationString(args.nameRes, 0); if (name == null) { className = null; args.outError[0] = args.tag + " does not specify android:name"; @@ -2793,7 +2806,8 @@ public class PackageParser { if (args.processRes != 0) { outInfo.processName = buildProcessName(owner.applicationInfo.packageName, - owner.applicationInfo.processName, args.sa.getNonResourceString(args.processRes), + owner.applicationInfo.processName, + args.sa.getNonConfigurationString(args.processRes, 0), args.flags, args.sepProcesses, args.outError); } diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java index a7fb31d..09fdf8d 100644 --- a/core/java/android/content/res/TypedArray.java +++ b/core/java/android/content/res/TypedArray.java @@ -148,6 +148,42 @@ public class TypedArray { } /** + * @hide + * Retrieve the string value for the attribute at <var>index</var> that is + * not allowed to change with the given configurations. + * + * @param index Index of attribute to retrieve. + * @param allowedChangingConfigs Bit mask of configurations from + * ActivityInfo that are allowed to change. + * + * @return String holding string data. Any styling information is + * removed. Returns null if the attribute is not defined. + */ + public String getNonConfigurationString(int index, int allowedChangingConfigs) { + index *= AssetManager.STYLE_NUM_ENTRIES; + final int[] data = mData; + final int type = data[index+AssetManager.STYLE_TYPE]; + if ((data[index+AssetManager.STYLE_CHANGING_CONFIGURATIONS]&~allowedChangingConfigs) != 0) { + return null; + } + if (type == TypedValue.TYPE_NULL) { + return null; + } else if (type == TypedValue.TYPE_STRING) { + return loadStringValueAt(index).toString(); + } + + TypedValue v = mValue; + if (getValueAt(index, v)) { + Log.w(Resources.TAG, "Converting to string: " + v); + CharSequence cs = v.coerceToString(); + return cs != null ? cs.toString() : null; + } + Log.w(Resources.TAG, "getString of bad type: 0x" + + Integer.toHexString(type)); + return null; + } + + /** * Retrieve the boolean value for the attribute at <var>index</var>. * * @param index Index of attribute to retrieve. diff --git a/core/java/android/database/BulkCursorToCursorAdaptor.java b/core/java/android/database/BulkCursorToCursorAdaptor.java index cf30dd9..1469ea2 100644 --- a/core/java/android/database/BulkCursorToCursorAdaptor.java +++ b/core/java/android/database/BulkCursorToCursorAdaptor.java @@ -43,25 +43,43 @@ public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor { try { mCount = mBulkCursor.count(); mWantsAllOnMoveCalls = mBulkCursor.getWantsAllOnMoveCalls(); - + // Search for the rowID column index and set it for our parent mColumns = mBulkCursor.getColumnNames(); - int length = mColumns.length; - for (int i = 0; i < length; i++) { - if (mColumns[i].equals("_id")) { - mRowIdColumnIndex = i; - break; - } - } + mRowIdColumnIndex = findRowIdColumnIndex(mColumns); } catch (RemoteException ex) { Log.e(TAG, "Setup failed because the remote process is dead"); } } /** + * Version of set() that does fewer Binder calls if the caller + * already knows BulkCursorToCursorAdaptor's properties. + */ + public void set(IBulkCursor bulkCursor, int count, int idIndex) { + mBulkCursor = bulkCursor; + mColumns = null; // lazily retrieved + mCount = count; + mRowIdColumnIndex = idIndex; + } + + /** + * Returns column index of "_id" column, or -1 if not found. + */ + public static int findRowIdColumnIndex(String[] columnNames) { + int length = columnNames.length; + for (int i = 0; i < length; i++) { + if (columnNames[i].equals("_id")) { + return i; + } + } + return -1; + } + + /** * Gets a SelfDataChangeOberserver that can be sent to a remote * process to receive change notifications over IPC. - * + * * @return A SelfContentObserver hooked up to this Cursor */ public synchronized IContentObserver getObserver() { @@ -190,6 +208,14 @@ public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor { @Override public String[] getColumnNames() { + if (mColumns == null) { + try { + mColumns = mBulkCursor.getColumnNames(); + } catch (RemoteException ex) { + Log.e(TAG, "Unable to fetch column names because the remote process is dead"); + return null; + } + } return mColumns; } @@ -255,4 +281,3 @@ public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor { } } } - diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java index 99db81b..c756825 100644 --- a/core/java/android/database/CursorWindow.java +++ b/core/java/android/database/CursorWindow.java @@ -44,7 +44,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { /** * Returns the starting position of this window within the entire * Cursor's result set. - * + * * @return the starting position of this window within the entire * Cursor's result set. */ diff --git a/core/java/android/database/IBulkCursor.java b/core/java/android/database/IBulkCursor.java index 24354fd..46790a3 100644 --- a/core/java/android/database/IBulkCursor.java +++ b/core/java/android/database/IBulkCursor.java @@ -27,11 +27,10 @@ import java.util.Map; * This interface provides a low-level way to pass bulk cursor data across * both process and language boundries. Application code should use the Cursor * interface directly. - * + * * {@hide} */ -public interface IBulkCursor extends IInterface -{ +public interface IBulkCursor extends IInterface { /** * Returns a BulkCursorWindow, which either has a reference to a shared * memory segment with the rows, or an array of JSON strings. @@ -60,7 +59,7 @@ public interface IBulkCursor extends IInterface public boolean deleteRow(int position) throws RemoteException; public void deactivate() throws RemoteException; - + public void close() throws RemoteException; public int requery(IContentObserver observer, CursorWindow window) throws RemoteException; @@ -87,4 +86,3 @@ public interface IBulkCursor extends IInterface static final int RESPOND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 10; static final int CLOSE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 11; } - diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java index e589f34..71fa2c2 100644 --- a/core/java/android/database/sqlite/SQLiteClosable.java +++ b/core/java/android/database/sqlite/SQLiteClosable.java @@ -19,14 +19,15 @@ package android.database.sqlite; import android.database.CursorWindow; /** - * An object create from a SQLiteDatabase that can be closed. + * An object created from a SQLiteDatabase that can be closed. */ -public abstract class SQLiteClosable { +public abstract class SQLiteClosable { private int mReferenceCount = 1; private Object mLock = new Object(); + protected abstract void onAllReferencesReleased(); - protected void onAllReferencesReleasedFromContainer(){} - + protected void onAllReferencesReleasedFromContainer() {} + public void acquireReference() { synchronized(mLock) { if (mReferenceCount <= 0) { @@ -36,7 +37,7 @@ public abstract class SQLiteClosable { mReferenceCount++; } } - + public void releaseReference() { synchronized(mLock) { mReferenceCount--; @@ -45,14 +46,14 @@ public abstract class SQLiteClosable { } } } - + public void releaseReferenceFromContainer() { synchronized(mLock) { mReferenceCount--; if (mReferenceCount == 0) { onAllReferencesReleasedFromContainer(); } - } + } } private String getObjInfo() { diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java index 6636473..5b4516d 100644 --- a/core/java/android/database/sqlite/SQLiteProgram.java +++ b/core/java/android/database/sqlite/SQLiteProgram.java @@ -61,6 +61,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { // only cache CRUD statements String prefixSql = mSql.substring(0, 6); if (!prefixSql.equalsIgnoreCase("INSERT") && !prefixSql.equalsIgnoreCase("UPDATE") && + !prefixSql.equalsIgnoreCase("REPLAC") && !prefixSql.equalsIgnoreCase("DELETE") && !prefixSql.equalsIgnoreCase("SELECT")) { mCompiledSql = new SQLiteCompiledSql(db, sql); nStatement = mCompiledSql.nStatement; diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 5a63ae1..3484d55 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -270,7 +270,13 @@ public class Camera { } /** - * Adds a pre-allocated buffer to the callback buffer queue. + * Adds a pre-allocated buffer to the callback buffer queue. Applications + * can add one or more buffers to the queue. When a preview frame arrives + * and there is still available buffer, buffer will be filled and it is + * removed from the queue. Then preview callback is invoked with the buffer. + * If a frame arrives and there is no buffer left, the frame is discarded. + * Applications should add the buffers back when they finish the processing. + * * Preview width and height can be determined from getPreviewSize, and bitsPerPixel can be * found from {@link android.hardware.Camera.Parameters#getPreviewFormat()} * and {@link android.graphics.ImageFormat#getBitsPerPixel(int)}. diff --git a/core/java/android/os/Power.java b/core/java/android/os/Power.java index b3df522..5a79215 100644 --- a/core/java/android/os/Power.java +++ b/core/java/android/os/Power.java @@ -18,7 +18,6 @@ package android.os; import java.io.IOException; import android.os.ServiceManager; -import android.os.storage.IMountService; /** * Class that provides access to some of the power management functions. @@ -101,15 +100,6 @@ public class Power */ public static void reboot(String reason) throws IOException { - IMountService mSvc = IMountService.Stub.asInterface( - ServiceManager.getService("mount")); - - if (mSvc != null) { - try { - mSvc.shutdown(); - } catch (Exception e) { - } - } rebootNative(reason); } diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl index ad4cb10..75455ab 100644 --- a/core/java/android/os/storage/IMountService.aidl +++ b/core/java/android/os/storage/IMountService.aidl @@ -18,6 +18,7 @@ package android.os.storage; import android.os.storage.IMountServiceListener; +import android.os.storage.IMountShutdownObserver; /** WARNING! Update IMountService.h and IMountService.cpp if you change this file. * In particular, the ordering of the methods below must match the @@ -142,6 +143,7 @@ interface IMountService /** * Shuts down the MountService and gracefully unmounts all external media. + * Invokes call back once the shutdown is complete. */ - void shutdown(); + void shutdown(IMountShutdownObserver observer); } diff --git a/core/java/android/os/storage/IMountShutdownObserver.aidl b/core/java/android/os/storage/IMountShutdownObserver.aidl new file mode 100644 index 0000000..0aa8a45 --- /dev/null +++ b/core/java/android/os/storage/IMountShutdownObserver.aidl @@ -0,0 +1,33 @@ +/* + * 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.storage; + +/** + * Callback class for receiving events related + * to shutdown. + * + * @hide - For internal consumption only. + */ +interface IMountShutdownObserver { + /** + * This method is called when the shutdown + * of MountService completed. + * @param statusCode indicates success or failure + * of the shutdown. + */ + void onShutDownComplete(int statusCode); +} diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index fdde591..1483f13 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1708,6 +1708,7 @@ public final class Settings { VOLUME_ALARM + APPEND_FOR_LAST_AUDIBLE, VOLUME_NOTIFICATION + APPEND_FOR_LAST_AUDIBLE, VOLUME_BLUETOOTH_SCO + APPEND_FOR_LAST_AUDIBLE, + VIBRATE_IN_SILENT, TEXT_AUTO_REPLACE, TEXT_AUTO_CAPS, TEXT_AUTO_PUNCTUATE, diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index f363828..c0e4600 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -374,6 +374,11 @@ class BluetoothEventLoop { Intent intent = null; if (propValues[1].equals("true")) { intent = new Intent(BluetoothDevice.ACTION_ACL_CONNECTED); + // Set the link timeout to 8000 slots (5 sec timeout) + // for bluetooth docks. + if (mBluetoothService.isBluetoothDock(address)) { + mBluetoothService.setLinkTimeout(address, 8000); + } } else { intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED); } diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java index e7d9d5b..2c73416 100644 --- a/core/java/android/server/BluetoothService.java +++ b/core/java/android/server/BluetoothService.java @@ -1910,6 +1910,13 @@ public class BluetoothService extends IBluetooth.Stub { return path; } + /*package */ void setLinkTimeout(String address, int num_slots) { + String path = getObjectPathFromAddress(address); + boolean result = setLinkTimeoutNative(path, num_slots); + + if (!result) log("Set Link Timeout to:" + num_slots + " slots failed"); + } + private static void log(String msg) { Log.d(TAG, msg); } @@ -1953,4 +1960,5 @@ public class BluetoothService extends IBluetooth.Stub { private native int addRfcommServiceRecordNative(String name, long uuidMsb, long uuidLsb, short channel); private native boolean removeServiceRecordNative(int handle); + private native boolean setLinkTimeoutNative(String path, int num_slots); } diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java index c17a724..aab76c4 100644 --- a/core/java/android/view/VelocityTracker.java +++ b/core/java/android/view/VelocityTracker.java @@ -259,8 +259,6 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { * * @param id Which pointer's velocity to return. * @return The previously computed X velocity. - * - * @hide Pending API approval */ public float getXVelocity(int id) { return mXVelocity[id]; @@ -272,8 +270,6 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { * * @param id Which pointer's velocity to return. * @return The previously computed Y velocity. - * - * @hide Pending API approval */ public float getYVelocity(int id) { return mYVelocity[id]; diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java index 2344c42..2b78d2d 100644 --- a/core/java/android/view/ViewConfiguration.java +++ b/core/java/android/view/ViewConfiguration.java @@ -102,6 +102,12 @@ public class ViewConfiguration { private static final int TOUCH_SLOP = 16; /** + * Distance a touch can wander before we think the user is attempting a paged scroll + * (in dips) + */ + private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 3; + + /** * Distance between the first touch and second touch to still be considered a double tap */ private static final int DOUBLE_TAP_SLOP = 100; @@ -140,6 +146,7 @@ public class ViewConfiguration { private final int mMaximumFlingVelocity; private final int mScrollbarSize; private final int mTouchSlop; + private final int mPagingTouchSlop; private final int mDoubleTapSlop; private final int mWindowTouchSlop; private final int mMaximumDrawingCacheSize; @@ -158,6 +165,7 @@ public class ViewConfiguration { mMaximumFlingVelocity = MAXIMUM_FLING_VELOCITY; mScrollbarSize = SCROLL_BAR_SIZE; mTouchSlop = TOUCH_SLOP; + mPagingTouchSlop = PAGING_TOUCH_SLOP; mDoubleTapSlop = DOUBLE_TAP_SLOP; mWindowTouchSlop = WINDOW_TOUCH_SLOP; //noinspection deprecation @@ -184,6 +192,7 @@ public class ViewConfiguration { mMaximumFlingVelocity = (int) (density * MAXIMUM_FLING_VELOCITY + 0.5f); mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f); mTouchSlop = (int) (density * TOUCH_SLOP + 0.5f); + mPagingTouchSlop = (int) (density * PAGING_TOUCH_SLOP + 0.5f); mDoubleTapSlop = (int) (density * DOUBLE_TAP_SLOP + 0.5f); mWindowTouchSlop = (int) (density * WINDOW_TOUCH_SLOP + 0.5f); @@ -339,6 +348,14 @@ public class ViewConfiguration { public int getScaledTouchSlop() { return mTouchSlop; } + + /** + * @return Distance a touch can wander before we think the user is scrolling a full page + * in dips + */ + public int getScaledPagingTouchSlop() { + return mPagingTouchSlop; + } /** * @return Distance between the first touch and second touch to still be diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java index 115499f..7da99ca 100644 --- a/core/java/android/webkit/LoadListener.java +++ b/core/java/android/webkit/LoadListener.java @@ -1057,7 +1057,7 @@ class LoadListener extends Handler implements EventHandler { mCacheLoader != null) ? HTTP_OK : mStatusCode; // pass content-type content-length and content-encoding final int nativeResponse = nativeCreateResponse( - mUrl, statusCode, mStatusText, + originalUrl(), statusCode, mStatusText, mMimeType, mContentLength, mEncoding); if (mHeaders != null) { mHeaders.getHeaders(new Headers.HeaderCallback() { @@ -1256,9 +1256,6 @@ class LoadListener extends Handler implements EventHandler { return; } - if (mOriginalUrl == null) { - mOriginalUrl = mUrl; - } // Cache the redirect response if (getErrorID() == OK) { @@ -1273,6 +1270,8 @@ class LoadListener extends Handler implements EventHandler { WebViewWorker.MSG_REMOVE_CACHE, this).sendToTarget(); } + // Saving a copy of the unstripped url for the response + mOriginalUrl = redirectTo; // This will strip the anchor setUrl(redirectTo); diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 8981419..fb15f78 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -192,6 +192,7 @@ public class WebSettings { private boolean mBuiltInZoomControls = false; private boolean mAllowFileAccess = true; private boolean mLoadWithOverviewMode = false; + private boolean mUseSystemOverscrollBackground = false; // private WebSettings, not accessible by the host activity static private int mDoubleTapToastCount = 3; @@ -470,6 +471,23 @@ public class WebSettings { } /** + * Set whether the WebView uses system background for over scroll + * background. If false, it will use the WebView's background. Default is + * false. + */ + public void setUseSystemOverscrollBackground(boolean system) { + mUseSystemOverscrollBackground = system; + } + + /** + * Returns true if this WebView uses system background instead of WebView + * background for over scroll background. + */ + public boolean getUseSystemOverscrollBackground() { + return mUseSystemOverscrollBackground; + } + + /** * Store whether the WebView is saving form data. */ public void setSaveFormData(boolean save) { diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java index 39edcad..016f016 100644 --- a/core/java/android/webkit/WebTextView.java +++ b/core/java/android/webkit/WebTextView.java @@ -377,11 +377,17 @@ import java.util.ArrayList; return; } mPreChange = postChange; - // This was simply a delete or a cut, so just delete the selection. - if (before > 0 && 0 == count) { - mWebView.deleteSelection(start, start + before); - // For this and all changes to the text, update our cache - updateCachedTextfield(); + if (0 == count) { + if (before > 0) { + // This was simply a delete or a cut, so just delete the + // selection. + mWebView.deleteSelection(start, start + before); + // For this and all changes to the text, update our cache + updateCachedTextfield(); + } + // before should never be negative, so whether it was a cut + // (handled above), or before is 0, in which case nothing has + // changed, we should return. return; } // Find the last character being replaced. If it can be represented by diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index e3fd29f..6f2d070 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -2199,14 +2199,15 @@ public class WebView extends AbsoluteLayout // Sets r to be our visible rectangle in content coordinates private void calcOurContentVisibleRect(Rect r) { calcOurVisibleRect(r); - r.left = viewToContentX(r.left); + // since we might overscroll, pin the rect to the bounds of the content + r.left = Math.max(viewToContentX(r.left), 0); // viewToContentY will remove the total height of the title bar. Add // the visible height back in to account for the fact that if the title // bar is partially visible, the part of the visible rect which is // displaying our content is displaced by that amount. - r.top = viewToContentY(r.top + getVisibleTitleHeight()); - r.right = viewToContentX(r.right); - r.bottom = viewToContentY(r.bottom); + r.top = Math.max(viewToContentY(r.top + getVisibleTitleHeight()), 0); + r.right = Math.min(viewToContentX(r.right), mContentWidth); + r.bottom = Math.min(viewToContentY(r.bottom), mContentHeight); } static class ViewSizeData { @@ -2305,9 +2306,11 @@ public class WebView extends AbsoluteLayout boolean clampedY) { mInOverScrollMode = false; int maxX = computeMaxScrollX(); - if (Math.abs(mMinZoomScale - mMaxZoomScale) < 0.01f && maxX == 0) { - // do not over scroll x if the page can't be zoomed and it just fits - // the screen + if (maxX == 0 && (Math.abs(mMinZoomScale - mMaxZoomScale) < 0.01f) + || !getSettings().supportZoom() + || !getSettings().getUseWideViewPort()) { + // do not over scroll x if the page just fits the screen and it + // can't zoom or the view doesn't use wide viewport scrollX = pinLocX(scrollX); } else if (scrollX < 0 || scrollX > maxX) { mInOverScrollMode = true; @@ -3112,7 +3115,8 @@ public class WebView extends AbsoluteLayout } int saveCount = canvas.save(); - if (mInOverScrollMode) { + if (mInOverScrollMode + && getSettings().getUseSystemOverscrollBackground()) { if (mOverScrollBackground == null) { mOverScrollBackground = new Paint(); Bitmap bm = BitmapFactory.decodeResource( @@ -3691,11 +3695,13 @@ public class WebView extends AbsoluteLayout return false; } - if (mShiftIsPressed == false && nativeCursorWantsKeyEvents() == false - && !nativeFocusIsPlugin() - && (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT - || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT)) { - setUpSelectXY(); + if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT + || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) { + if (nativeFocusIsPlugin()) { + mShiftIsPressed = true; + } else if (!nativeCursorWantsKeyEvents() && !mShiftIsPressed) { + setUpSelectXY(); + } } if (keyCode >= KeyEvent.KEYCODE_DPAD_UP @@ -3834,7 +3840,10 @@ public class WebView extends AbsoluteLayout if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) { - if (commitCopy()) { + if (nativeFocusIsPlugin()) { + mShiftIsPressed = false; + return true; + } else if (commitCopy()) { return true; } } @@ -4195,7 +4204,9 @@ public class WebView extends AbsoluteLayout public boolean dispatchKeyEvent(KeyEvent event) { boolean dispatch = true; - if (!inEditingMode()) { + // Textfields and plugins need to receive the shift up key even if + // another key was released while the shift key was held down. + if (!inEditingMode() && !nativeFocusIsPlugin()) { if (event.getAction() == KeyEvent.ACTION_DOWN) { mGotKeyDown = true; } else { diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index e87455c..a1c3fa2 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -1641,7 +1641,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mResurrectToPosition = mSelectedPosition; } } else { - if (mFiltered) { + if (mFiltered && !mPopupHidden) { // Show the type filter only if a filter is in effect showPopup(); } @@ -2773,7 +2773,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int lastPos = firstPos + getChildCount() - 1; int viewTravelCount = 0; - if (position < firstPos) { + if (position <= firstPos) { final int boundPosFromLast = lastPos - boundPosition; if (boundPosFromLast < 1) { // Moving would shift our bound position off the screen. Abort. @@ -2789,7 +2789,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te viewTravelCount = posTravel; mMode = MOVE_UP_POS; } - } else if (position > lastPos) { + } else if (position >= lastPos) { final int boundPosFromFirst = boundPosition - firstPos; if (boundPosFromFirst < 1) { // Moving would shift our bound position off the screen. Abort. @@ -3510,7 +3510,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (mPopup != null) { mPopup.dismiss(); } - mPopupHidden = false; } /** diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 1a9c0df5..d4552e3 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -3480,10 +3480,41 @@ public class ListView extends AbsListView { * @return A new array which contains the id of each checked item in the * list. * - * @deprecated Use {@link #getCheckedItemIds()} instead. + * @deprecated Use {@link #getCheckedItemIds()} instead. */ public long[] getCheckItemIds() { - return getCheckedItemIds(); + // Use new behavior that correctly handles stable ID mapping. + if (mAdapter != null && mAdapter.hasStableIds()) { + return getCheckedItemIds(); + } + + // Old behavior was buggy, but would sort of work for adapters without stable IDs. + // Fall back to it to support legacy apps. + if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null && mAdapter != null) { + final SparseBooleanArray states = mCheckStates; + final int count = states.size(); + final long[] ids = new long[count]; + final ListAdapter adapter = mAdapter; + + int checkedCount = 0; + for (int i = 0; i < count; i++) { + if (states.valueAt(i)) { + ids[checkedCount++] = adapter.getItemId(states.keyAt(i)); + } + } + + // Trim array if needed. mCheckStates may contain false values + // resulting in checkedCount being smaller than count. + if (checkedCount == count) { + return ids; + } else { + final long[] result = new long[checkedCount]; + System.arraycopy(ids, 0, result, 0, checkedCount); + + return result; + } + } + return new long[0]; } /** diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 7b21be5..64c9c99 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -6989,6 +6989,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + if (!isShown()) { + return false; + } + final boolean isPassword = isPasswordInputType(mInputType); if (!isPassword) { diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java index 37898a1..51cd0f8 100644 --- a/core/java/com/android/internal/app/ShutdownThread.java +++ b/core/java/com/android/internal/app/ShutdownThread.java @@ -28,12 +28,13 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.os.Handler; +import android.os.Power; import android.os.PowerManager; import android.os.RemoteException; -import android.os.Power; import android.os.ServiceManager; import android.os.SystemClock; import android.os.storage.IMountService; +import android.os.storage.IMountShutdownObserver; import com.android.internal.telephony.ITelephony; import android.util.Log; @@ -46,16 +47,20 @@ public final class ShutdownThread extends Thread { private static final int PHONE_STATE_POLL_SLEEP_MSEC = 500; // maximum time we wait for the shutdown broadcast before going on. private static final int MAX_BROADCAST_TIME = 10*1000; + private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000; // state tracking private static Object sIsStartedGuard = new Object(); private static boolean sIsStarted = false; + private static boolean mReboot; + private static String mRebootReason; + // static instance of this thread private static final ShutdownThread sInstance = new ShutdownThread(); - private final Object mBroadcastDoneSync = new Object(); - private boolean mBroadcastDone; + private final Object mActionDoneSync = new Object(); + private boolean mActionDone; private Context mContext; private PowerManager mPowerManager; private PowerManager.WakeLock mWakeLock; @@ -64,12 +69,13 @@ public final class ShutdownThread extends Thread { private ShutdownThread() { } - /** + /** * Request a clean shutdown, waiting for subsystems to clean up their * state etc. Must be called from a Looper thread in which its UI * is shown. - * + * * @param context Context used to display the shutdown progress dialog. + * @param confirm true if user confirmation is needed before shutting down. */ public static void shutdown(final Context context, boolean confirm) { // ensure that only one thread is trying to power down. @@ -106,6 +112,21 @@ public final class ShutdownThread extends Thread { } } + /** + * Request a clean shutdown, waiting for subsystems to clean up their + * state etc. Must be called from a Looper thread in which its UI + * is shown. + * + * @param context Context used to display the shutdown progress dialog. + * @param reason code to pass to the kernel (e.g. "recovery"), or null. + * @param confirm true if user confirmation is needed before shutting down. + */ + public static void reboot(final Context context, String reason, boolean confirm) { + mReboot = true; + mRebootReason = reason; + shutdown(context, confirm); + } + private static void beginShutdownSequence(Context context) { synchronized (sIsStartedGuard) { sIsStarted = true; @@ -145,13 +166,13 @@ public final class ShutdownThread extends Thread { sInstance.start(); } - void broadcastDone() { - synchronized (mBroadcastDoneSync) { - mBroadcastDone = true; - mBroadcastDoneSync.notifyAll(); + void actionDone() { + synchronized (mActionDoneSync) { + mActionDone = true; + mActionDoneSync.notifyAll(); } } - + /** * Makes sure we handle the shutdown gracefully. * Shuts off power regardless of radio and bluetooth state if the alloted time has passed. @@ -163,27 +184,27 @@ public final class ShutdownThread extends Thread { BroadcastReceiver br = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // We don't allow apps to cancel this, so ignore the result. - broadcastDone(); + actionDone(); } }; Log.i(TAG, "Sending shutdown broadcast..."); // First send the high-level shut down broadcast. - mBroadcastDone = false; + mActionDone = false; mContext.sendOrderedBroadcast(new Intent(Intent.ACTION_SHUTDOWN), null, br, mHandler, 0, null, null); final long endTime = System.currentTimeMillis() + MAX_BROADCAST_TIME; - synchronized (mBroadcastDoneSync) { - while (!mBroadcastDone) { + synchronized (mActionDoneSync) { + while (!mActionDone) { long delay = endTime - System.currentTimeMillis(); if (delay <= 0) { Log.w(TAG, "Shutdown broadcast timed out"); break; } try { - mBroadcastDoneSync.wait(delay); + mActionDoneSync.wait(delay); } catch (InterruptedException e) { } } @@ -262,17 +283,50 @@ public final class ShutdownThread extends Thread { } // Shutdown MountService to ensure media is in a safe state - try { - if (mount != null) { - mount.shutdown(); - } else { - Log.w(TAG, "MountService unavailable for shutdown"); + IMountShutdownObserver observer = new IMountShutdownObserver.Stub() { + public void onShutDownComplete(int statusCode) throws RemoteException { + Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown"); + actionDone(); + } + }; + + Log.i(TAG, "Shutting down MountService"); + // Set initial variables and time out time. + mActionDone = false; + final long endShutTime = System.currentTimeMillis() + MAX_SHUTDOWN_WAIT_TIME; + synchronized (mActionDoneSync) { + try { + if (mount != null) { + mount.shutdown(observer); + } else { + Log.w(TAG, "MountService unavailable for shutdown"); + } + } catch (Exception e) { + Log.e(TAG, "Exception during MountService shutdown", e); + } + while (!mActionDone) { + long delay = endShutTime - System.currentTimeMillis(); + if (delay <= 0) { + Log.w(TAG, "Shutdown wait timed out"); + break; + } + try { + mActionDoneSync.wait(delay); + } catch (InterruptedException e) { + } + } + } + + if (mReboot) { + Log.i(TAG, "Rebooting, reason: " + mRebootReason); + try { + Power.reboot(mRebootReason); + } catch (Exception e) { + Log.e(TAG, "Reboot failed, will attempt shutdown instead", e); } - } catch (Exception e) { - Log.e(TAG, "Exception during MountService shutdown", e); } - //shutdown power + // Shutdown power Log.i(TAG, "Performing low-level shutdown..."); Power.shutdown(); } diff --git a/core/java/com/android/internal/content/SelectionBuilder.java b/core/java/com/android/internal/content/SelectionBuilder.java new file mode 100644 index 0000000..0e29411 --- /dev/null +++ b/core/java/com/android/internal/content/SelectionBuilder.java @@ -0,0 +1,121 @@ +/* + * 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 com.android.internal.content; + +import android.content.ContentValues; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.text.TextUtils; + +import java.util.ArrayList; + +/** + * Helper for building selection clauses for {@link SQLiteDatabase}. Each + * appended clause is combined using {@code AND}. This class is <em>not</em> + * thread safe. + * + * @hide + */ +public class SelectionBuilder { + private StringBuilder mSelection = new StringBuilder(); + private ArrayList<String> mSelectionArgs = new ArrayList<String>(); + + /** + * Reset any internal state, allowing this builder to be recycled. + */ + public SelectionBuilder reset() { + mSelection.setLength(0); + mSelectionArgs.clear(); + return this; + } + + /** + * Append the given selection clause to the internal state. Each clause is + * surrounded with parenthesis and combined using {@code AND}. + */ + public SelectionBuilder append(String selection, String... selectionArgs) { + if (TextUtils.isEmpty(selection)) { + if (selectionArgs != null && selectionArgs.length > 0) { + throw new IllegalArgumentException( + "Valid selection required when including arguments"); + } + + // Shortcut when clause is empty + return this; + } + + if (mSelection.length() > 0) { + mSelection.append(" AND "); + } + + mSelection.append("(").append(selection).append(")"); + for (String arg : selectionArgs) { + mSelectionArgs.add(arg); + } + + return this; + } + + /** + * Return selection string for current internal state. + * + * @see #getSelectionArgs() + */ + public String getSelection() { + return mSelection.toString(); + } + + /** + * Return selection arguments for current internal state. + * + * @see #getSelection() + */ + public String[] getSelectionArgs() { + return mSelectionArgs.toArray(new String[mSelectionArgs.size()]); + } + + /** + * Execute query using the current internal state as {@code WHERE} clause. + * Missing arguments as treated as {@code null}. + */ + public Cursor query(SQLiteDatabase db, String table, String[] columns, String orderBy) { + return query(db, table, columns, null, null, orderBy, null); + } + + /** + * Execute query using the current internal state as {@code WHERE} clause. + */ + public Cursor query(SQLiteDatabase db, String table, String[] columns, String groupBy, + String having, String orderBy, String limit) { + return db.query(table, columns, getSelection(), getSelectionArgs(), groupBy, having, + orderBy, limit); + } + + /** + * Execute update using the current internal state as {@code WHERE} clause. + */ + public int update(SQLiteDatabase db, String table, ContentValues values) { + return db.update(table, values, getSelection(), getSelectionArgs()); + } + + /** + * Execute delete using the current internal state as {@code WHERE} clause. + */ + public int delete(SQLiteDatabase db, String table) { + return db.delete(table, getSelection(), getSelectionArgs()); + } +} diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 9965fe5..b6f3997 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -331,12 +331,14 @@ static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStream* stream, // i.e. dynamically allocated, since its lifetime may exceed the current stack // frame. static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, - jobject options, bool allowPurgeable) { + jobject options, bool allowPurgeable, + bool forcePurgeable = false) { int sampleSize = 1; SkImageDecoder::Mode mode = SkImageDecoder::kDecodePixels_Mode; SkBitmap::Config prefConfig = SkBitmap::kNo_Config; bool doDither = true; - bool isPurgeable = allowPurgeable && optionsPurgeable(env, options); + bool isPurgeable = forcePurgeable || + (allowPurgeable && optionsPurgeable(env, options)); bool reportSizeToVM = optionsReportSizeToVM(env, options); if (NULL != options) { @@ -568,8 +570,10 @@ static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jobject options) { // BitmapFactory$Options SkStream* stream; Asset* asset = reinterpret_cast<Asset*>(native_asset); + // assets can always be rebuilt, so force this + bool forcePurgeable = true; - if (optionsPurgeable(env, options)) { + if (forcePurgeable || optionsPurgeable(env, options)) { // if we could "ref/reopen" the asset, we may not need to copy it here // and we could assume optionsShareable, since assets are always RO stream = copyAssetToStream(asset); @@ -582,7 +586,7 @@ static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, stream = new AssetStreamAdaptor(asset); } SkAutoUnref aur(stream); - return doDecode(env, stream, padding, options, true); + return doDecode(env, stream, padding, options, true, forcePurgeable); } static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray, diff --git a/core/jni/android/graphics/YuvToJpegEncoder.cpp b/core/jni/android/graphics/YuvToJpegEncoder.cpp index 819cce8..0a0c5b3 100644 --- a/core/jni/android/graphics/YuvToJpegEncoder.cpp +++ b/core/jni/android/graphics/YuvToJpegEncoder.cpp @@ -49,19 +49,16 @@ bool YuvToJpegEncoder::encode(SkWStream* stream, void* inYuv, int width, void YuvToJpegEncoder::setJpegCompressStruct(jpeg_compress_struct* cinfo, int width, int height, int quality) { - jpeg_set_quality(cinfo, quality, TRUE); - cinfo->image_width = width; cinfo->image_height = height; - cinfo->input_components = 3; cinfo->in_color_space = JCS_YCbCr; jpeg_set_defaults(cinfo); + + jpeg_set_quality(cinfo, quality, TRUE); jpeg_set_colorspace(cinfo, JCS_YCbCr); cinfo->raw_data_in = TRUE; - cinfo->dct_method = JDCT_IFAST; - configSamplingFactors(cinfo); } diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp index ea64305..4420aca 100644 --- a/core/jni/android_server_BluetoothService.cpp +++ b/core/jni/android_server_BluetoothService.cpp @@ -861,6 +861,26 @@ static jboolean removeServiceRecordNative(JNIEnv *env, jobject object, jint hand return JNI_FALSE; } +static jboolean setLinkTimeoutNative(JNIEnv *env, jobject object, jstring object_path, + jint num_slots) { + LOGV(__FUNCTION__); +#ifdef HAVE_BLUETOOTH + native_data_t *nat = get_native_data(env, object); + if (nat) { + const char *c_object_path = env->GetStringUTFChars(object_path, NULL); + DBusMessage *reply = dbus_func_args(env, nat->conn, + get_adapter_path(env, object), + DBUS_ADAPTER_IFACE, "SetLinkTimeout", + DBUS_TYPE_OBJECT_PATH, &c_object_path, + DBUS_TYPE_UINT32, &num_slots, + DBUS_TYPE_INVALID); + env->ReleaseStringUTFChars(object_path, c_object_path); + return reply ? JNI_TRUE : JNI_FALSE; + } +#endif + return JNI_FALSE; +} + static JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"classInitNative", "()V", (void*)classInitNative}, @@ -905,6 +925,7 @@ static JNINativeMethod sMethods[] = { {"discoverServicesNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *)discoverServicesNative}, {"addRfcommServiceRecordNative", "(Ljava/lang/String;JJS)I", (void *)addRfcommServiceRecordNative}, {"removeServiceRecordNative", "(I)Z", (void *)removeServiceRecordNative}, + {"setLinkTimeoutNative", "(Ljava/lang/String;I)Z", (void *)setLinkTimeoutNative}, }; int register_android_server_BluetoothService(JNIEnv *env) { diff --git a/core/res/res/drawable-hdpi/stat_notify_car_mode.png b/core/res/res/drawable-hdpi/stat_notify_car_mode.png Binary files differindex 6c51b32..03499a4 100644 --- a/core/res/res/drawable-hdpi/stat_notify_car_mode.png +++ b/core/res/res/drawable-hdpi/stat_notify_car_mode.png diff --git a/core/res/res/drawable-hdpi/stat_sys_tether_bluetooth.png b/core/res/res/drawable-hdpi/stat_sys_tether_bluetooth.png Binary files differnew file mode 100644 index 0000000..e43fbae --- /dev/null +++ b/core/res/res/drawable-hdpi/stat_sys_tether_bluetooth.png diff --git a/core/res/res/drawable-hdpi/stat_sys_tether_general.png b/core/res/res/drawable-hdpi/stat_sys_tether_general.png Binary files differnew file mode 100644 index 0000000..e43fbae --- /dev/null +++ b/core/res/res/drawable-hdpi/stat_sys_tether_general.png diff --git a/core/res/res/drawable-hdpi/stat_sys_tether_usb.png b/core/res/res/drawable-hdpi/stat_sys_tether_usb.png Binary files differindex 4c14c07..c6c533d 100755..100644 --- a/core/res/res/drawable-hdpi/stat_sys_tether_usb.png +++ b/core/res/res/drawable-hdpi/stat_sys_tether_usb.png diff --git a/core/res/res/drawable-hdpi/stat_sys_tether_wifi.png b/core/res/res/drawable-hdpi/stat_sys_tether_wifi.png Binary files differnew file mode 100644 index 0000000..9fcadef --- /dev/null +++ b/core/res/res/drawable-hdpi/stat_sys_tether_wifi.png diff --git a/core/res/res/drawable-mdpi/stat_notify_car_mode.png b/core/res/res/drawable-mdpi/stat_notify_car_mode.png Binary files differindex c664244..0272e6b 100644 --- a/core/res/res/drawable-mdpi/stat_notify_car_mode.png +++ b/core/res/res/drawable-mdpi/stat_notify_car_mode.png diff --git a/core/res/res/drawable-mdpi/stat_sys_tether_bluetooth.png b/core/res/res/drawable-mdpi/stat_sys_tether_bluetooth.png Binary files differnew file mode 100644 index 0000000..efb64ad --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_tether_bluetooth.png diff --git a/core/res/res/drawable-mdpi/stat_sys_tether_general.png b/core/res/res/drawable-mdpi/stat_sys_tether_general.png Binary files differnew file mode 100644 index 0000000..efb64ad --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_tether_general.png diff --git a/core/res/res/drawable-mdpi/stat_sys_tether_usb.png b/core/res/res/drawable-mdpi/stat_sys_tether_usb.png Binary files differindex 2d0da4c..73f1a81 100644 --- a/core/res/res/drawable-mdpi/stat_sys_tether_usb.png +++ b/core/res/res/drawable-mdpi/stat_sys_tether_usb.png diff --git a/core/res/res/drawable-mdpi/stat_sys_tether_wifi.png b/core/res/res/drawable-mdpi/stat_sys_tether_wifi.png Binary files differnew file mode 100644 index 0000000..d448491 --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_tether_wifi.png diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index e68f214..3fb9607 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -2251,4 +2251,8 @@ <string name="car_mode_disable_notification_title">Car mode enabled</string> <string name="car_mode_disable_notification_message">Select to exit car mode.</string> + <!-- Strings for tethered notification --> + <!-- Shown when the device is tethered --> + <string name="tethered_notification_title">Tethering active</string> + <string name="tethered_notification_message">Touch to configure</string> </resources> diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h index 0e796dc..b701ce7 100644 --- a/include/utils/ResourceTypes.h +++ b/include/utils/ResourceTypes.h @@ -631,6 +631,8 @@ public: void restart(); + const ResStringPool& getStrings() const; + event_code_t getEventType() const; // Note, unlike XmlPullParser, the first call to next() will return // START_TAG of the first element. @@ -716,8 +718,6 @@ public: void uninit(); - const ResStringPool& getStrings() const; - private: friend class ResXMLParser; diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 6041b83..4614b53 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -22,6 +22,7 @@ import android.net.LocalSocket; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.util.ArrayList; /** @@ -57,12 +58,12 @@ public class KeyStore { public byte[] get(byte[] key) { ArrayList<byte[]> values = execute('g', key); - return (values == null || values.size() == 0) ? null : values.get(0); + return (values == null || values.isEmpty()) ? null : values.get(0); } public String get(String key) { - byte[] value = get(key.getBytes()); - return (value == null) ? null : new String(value); + byte[] value = get(getBytes(key)); + return (value == null) ? null : toString(value); } public boolean put(byte[] key, byte[] value) { @@ -71,7 +72,7 @@ public class KeyStore { } public boolean put(String key, String value) { - return put(key.getBytes(), value.getBytes()); + return put(getBytes(key), getBytes(value)); } public boolean delete(byte[] key) { @@ -80,7 +81,7 @@ public class KeyStore { } public boolean delete(String key) { - return delete(key.getBytes()); + return delete(getBytes(key)); } public boolean contains(byte[] key) { @@ -89,7 +90,7 @@ public class KeyStore { } public boolean contains(String key) { - return contains(key.getBytes()); + return contains(getBytes(key)); } public byte[][] saw(byte[] prefix) { @@ -98,13 +99,13 @@ public class KeyStore { } public String[] saw(String prefix) { - byte[][] values = saw(prefix.getBytes()); + byte[][] values = saw(getBytes(prefix)); if (values == null) { return null; } String[] strings = new String[values.length]; for (int i = 0; i < values.length; ++i) { - strings[i] = new String(values[i]); + strings[i] = toString(values[i]); } return strings; } @@ -120,7 +121,7 @@ public class KeyStore { } public boolean password(String oldPassword, String newPassword) { - return password(oldPassword.getBytes(), newPassword.getBytes()); + return password(getBytes(oldPassword), getBytes(newPassword)); } public boolean password(byte[] password) { @@ -128,7 +129,7 @@ public class KeyStore { } public boolean password(String password) { - return password(password.getBytes()); + return password(getBytes(password)); } public boolean lock() { @@ -142,7 +143,7 @@ public class KeyStore { } public boolean unlock(String password) { - return unlock(password.getBytes()); + return unlock(getBytes(password)); } public int getLastError() { @@ -208,4 +209,22 @@ public class KeyStore { } return null; } + + private static byte[] getBytes(String string) { + try { + return string.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + // will never happen + throw new RuntimeException(e); + } + } + + private static String toString(byte[] bytes) { + try { + return new String(bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + // will never happen + throw new RuntimeException(e); + } + } } diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java index 569d8da..6630a4f 100755 --- a/keystore/tests/src/android/security/KeyStoreTest.java +++ b/keystore/tests/src/android/security/KeyStoreTest.java @@ -39,6 +39,9 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { private static final String TEST_KEYNAME2 = "testkey2"; private static final String TEST_KEYVALUE = "test value"; + // "Hello, World" in Chinese + private static final String TEST_I18N = "\u4F60\u597D, \u4E16\u754C"; + private KeyStore mKeyStore = null; public KeyStoreTest() { @@ -83,6 +86,14 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE)); } + public void testI18n() throws Exception { + assertFalse(mKeyStore.put(TEST_I18N, TEST_I18N)); + assertFalse(mKeyStore.contains(TEST_I18N)); + mKeyStore.password(TEST_I18N); + assertTrue(mKeyStore.put(TEST_I18N, TEST_I18N)); + assertTrue(mKeyStore.contains(TEST_I18N)); + } + public void testDelete() throws Exception { assertTrue(mKeyStore.delete(TEST_KEYNAME)); mKeyStore.password(TEST_PASSWD); diff --git a/libs/audioflinger/Android.mk b/libs/audioflinger/Android.mk index b68bfc1..870c0b8 100644 --- a/libs/audioflinger/Android.mk +++ b/libs/audioflinger/Android.mk @@ -24,7 +24,7 @@ endif LOCAL_SHARED_LIBRARIES := \ libcutils \ libutils \ - libbinder \ + libbinder \ libmedia \ libhardware_legacy @@ -85,7 +85,7 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libcutils \ libutils \ - libbinder \ + libbinder \ libmedia \ libhardware_legacy @@ -114,9 +114,17 @@ ifeq ($(AUDIO_POLICY_TEST),true) endif ifeq ($(TARGET_SIMULATOR),true) - ifeq ($(HOST_OS),linux) - LOCAL_LDLIBS += -lrt -lpthread - endif + ifeq ($(HOST_OS),linux) + LOCAL_LDLIBS += -lrt -lpthread + endif +endif + +ifeq ($(BOARD_USE_LVMX),true) + LOCAL_CFLAGS += -DLVMX + LOCAL_C_INCLUDES += vendor/nxp + LOCAL_STATIC_LIBRARIES += liblifevibes + LOCAL_SHARED_LIBRARIES += liblvmxservice +# LOCAL_SHARED_LIBRARIES += liblvmxipc endif include $(BUILD_SHARED_LIBRARY) diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index 8089389..7902212 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -47,6 +47,10 @@ #include "A2dpAudioInterface.h" #endif +#ifdef LVMX +#include "lifevibes.h" +#endif + // ---------------------------------------------------------------------------- // the sim build doesn't have gettid @@ -132,6 +136,9 @@ AudioFlinger::AudioFlinger() } else { LOGE("Couldn't even initialize the stubbed audio hardware!"); } +#ifdef LVMX + LifeVibes::init(); +#endif } AudioFlinger::~AudioFlinger() @@ -411,6 +418,11 @@ status_t AudioFlinger::setMode(int mode) AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_HW_SET_MODE; status_t ret = mAudioHardware->setMode(mode); +#ifdef LVMX + if (NO_ERROR == ret) { + LifeVibes::setMode(mode); + } +#endif mHardwareStatus = AUDIO_HW_IDLE; return ret; } @@ -566,11 +578,37 @@ status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs) return PERMISSION_DENIED; } +#ifdef LVMX + AudioParameter param = AudioParameter(keyValuePairs); + LifeVibes::setParameters(ioHandle,keyValuePairs); + String8 key = String8(AudioParameter::keyRouting); + int device; + if (NO_ERROR != param.getInt(key, device)) { + device = -1; + } + + key = String8(LifevibesTag); + String8 value; + int musicEnabled = -1; + if (NO_ERROR == param.get(key, value)) { + if (value == LifevibesEnable) { + musicEnabled = 1; + } else if (value == LifevibesDisable) { + musicEnabled = 0; + } + } +#endif + // ioHandle == 0 means the parameters are global to the audio hardware interface if (ioHandle == 0) { AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_SET_PARAMETER; result = mAudioHardware->setParameters(keyValuePairs); +#ifdef LVMX + if ((NO_ERROR == result) && (musicEnabled != -1)) { + LifeVibes::enableMusic((bool) musicEnabled); + } +#endif mHardwareStatus = AUDIO_HW_IDLE; return result; } @@ -586,7 +624,13 @@ status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs) } } if (thread != NULL) { - return thread->setParameters(keyValuePairs); + result = thread->setParameters(keyValuePairs); +#ifdef LVMX + if ((NO_ERROR == result) && (device != -1)) { + LifeVibes::setDevice(LifeVibes::threadIdToAudioOutputType(thread->id()), device); + } +#endif + return result; } return BAD_VALUE; } @@ -1058,12 +1102,24 @@ uint32_t AudioFlinger::PlaybackThread::latency() const status_t AudioFlinger::PlaybackThread::setMasterVolume(float value) { +#ifdef LVMX + int audioOutputType = LifeVibes::getMixerType(mId, mType); + if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) { + LifeVibes::setMasterVolume(audioOutputType, value); + } +#endif mMasterVolume = value; return NO_ERROR; } status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted) { +#ifdef LVMX + int audioOutputType = LifeVibes::getMixerType(mId, mType); + if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) { + LifeVibes::setMasterMute(audioOutputType, muted); + } +#endif mMasterMute = muted; return NO_ERROR; } @@ -1080,12 +1136,24 @@ bool AudioFlinger::PlaybackThread::masterMute() const status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value) { +#ifdef LVMX + int audioOutputType = LifeVibes::getMixerType(mId, mType); + if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) { + LifeVibes::setStreamVolume(audioOutputType, stream, value); + } +#endif mStreamTypes[stream].volume = value; return NO_ERROR; } status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted) { +#ifdef LVMX + int audioOutputType = LifeVibes::getMixerType(mId, mType); + if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) { + LifeVibes::setStreamMute(audioOutputType, stream, muted); + } +#endif mStreamTypes[stream].mute = muted; return NO_ERROR; } @@ -1333,6 +1401,12 @@ bool AudioFlinger::MixerThread::threadLoop() mLastWriteTime = systemTime(); mInWrite = true; mBytesWritten += mixBufferSize; +#ifdef LVMX + int audioOutputType = LifeVibes::getMixerType(mId, mType); + if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) { + LifeVibes::process(audioOutputType, curBuf, mixBufferSize); + } +#endif int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize); if (bytesWritten < 0) mBytesWritten -= mixBufferSize; mNumWrites++; @@ -1376,6 +1450,29 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track uint32_t mixerStatus = MIXER_IDLE; // find out which tracks need to be processed size_t count = activeTracks.size(); + + float masterVolume = mMasterVolume; + bool masterMute = mMasterMute; + +#ifdef LVMX + bool tracksConnectedChanged = false; + bool stateChanged = false; + + int audioOutputType = LifeVibes::getMixerType(mId, mType); + if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) + { + int activeTypes = 0; + for (size_t i=0 ; i<count ; i++) { + sp<Track> t = activeTracks[i].promote(); + if (t == 0) continue; + Track* const track = t.get(); + int iTracktype=track->type(); + activeTypes |= 1<<track->type(); + } + LifeVibes::computeVolumes(audioOutputType, activeTypes, tracksConnectedChanged, stateChanged, masterVolume, masterMute); + } +#endif + for (size_t i=0 ; i<count ; i++) { sp<Track> t = activeTracks[i].promote(); if (t == 0) continue; @@ -1393,15 +1490,27 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track // compute volume for this track int16_t left, right; - if (track->isMuted() || mMasterMute || track->isPausing() || + if (track->isMuted() || masterMute || track->isPausing() || mStreamTypes[track->type()].mute) { left = right = 0; if (track->isPausing()) { track->setPaused(); } } else { + // read original volumes with volume control float typeVolume = mStreamTypes[track->type()].volume; - float v = mMasterVolume * typeVolume; +#ifdef LVMX + bool streamMute=false; + // read the volume from the LivesVibes audio engine. + if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) + { + LifeVibes::getStreamVolumes(audioOutputType, track->type(), &typeVolume, &streamMute); + if (streamMute) { + typeVolume = 0; + } + } +#endif + float v = masterVolume * typeVolume; float v_clamped = v * cblk->volume[0]; if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN; left = int16_t(v_clamped); @@ -1427,7 +1536,13 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track // do not apply ramp param = AudioMixer::RAMP_VOLUME; } - +#ifdef LVMX + if ( tracksConnectedChanged || stateChanged ) + { + // only do the ramp when the volume is changed by the user / application + param = AudioMixer::VOLUME; + } +#endif mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left); mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right); mAudioMixer->setParameter( @@ -3652,6 +3767,18 @@ int AudioFlinger::openOutput(uint32_t *pDevices, } else { thread = new MixerThread(this, output, ++mNextThreadId); LOGV("openOutput() created mixer output: ID %d thread %p", mNextThreadId, thread); + +#ifdef LVMX + unsigned bitsPerSample = + (format == AudioSystem::PCM_16_BIT) ? 16 : + ((format == AudioSystem::PCM_8_BIT) ? 8 : 0); + unsigned channelCount = (channels == AudioSystem::CHANNEL_OUT_STEREO) ? 2 : 1; + int audioOutputType = LifeVibes::threadIdToAudioOutputType(thread->id()); + + LifeVibes::init_aot(audioOutputType, samplingRate, bitsPerSample, channelCount); + LifeVibes::setDevice(audioOutputType, *pDevices); +#endif + } mPlaybackThreads.add(mNextThreadId, thread); diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp index ae215d1..d481150 100644 --- a/libs/audioflinger/AudioHardwareStub.cpp +++ b/libs/audioflinger/AudioHardwareStub.cpp @@ -166,7 +166,7 @@ status_t AudioStreamOutStub::getRenderPosition(uint32_t *dspFrames) // ---------------------------------------------------------------------------- status_t AudioStreamInStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate, - AudioSystem::audio_in_acoustics acoustics) + AudioSystem::audio_in_acoustics acoustics) { return NO_ERROR; } diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp index cfcc3ea..2b0a6c8 100644 --- a/libs/audioflinger/AudioPolicyManagerBase.cpp +++ b/libs/audioflinger/AudioPolicyManagerBase.cpp @@ -344,6 +344,7 @@ void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSyst { LOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState); + bool forceVolumeReeval = false; switch(usage) { case AudioSystem::FOR_COMMUNICATION: if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO && @@ -374,6 +375,7 @@ void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSyst config != AudioSystem::FORCE_BT_DESK_DOCK && config != AudioSystem::FORCE_WIRED_ACCESSORY) { LOGW("setForceUse() invalid config %d for FOR_DOCK", config); } + forceVolumeReeval = true; mForceUse[usage] = config; break; default: @@ -388,6 +390,9 @@ void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSyst #endif updateDeviceForStrategy(); setOutputDevice(mHardwareOutput, newDevice); + if (forceVolumeReeval) { + applyStreamVolumes(mHardwareOutput, newDevice); + } } AudioSystem::forced_config AudioPolicyManagerBase::getForceUse(AudioSystem::force_use usage) diff --git a/libs/audioflinger/AudioResampler.h b/libs/audioflinger/AudioResampler.h index 39656c0..2dfac76 100644 --- a/libs/audioflinger/AudioResampler.h +++ b/libs/audioflinger/AudioResampler.h @@ -76,8 +76,8 @@ protected: int32_t mInSampleRate; AudioBufferProvider::Buffer mBuffer; union { - int16_t mVolume[2]; - uint32_t mVolumeRL; + int16_t mVolume[2]; + uint32_t mVolumeRL; }; int16_t mTargetVolume[2]; format mFormat; diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 38d8412..7e0f881 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -625,6 +625,10 @@ void ResXMLParser::restart() mCurNode = NULL; mEventCode = mTree.mError == NO_ERROR ? START_DOCUMENT : BAD_DOCUMENT; } +const ResStringPool& ResXMLParser::getStrings() const +{ + return mTree.mStrings; +} ResXMLParser::event_code_t ResXMLParser::getEventType() const { @@ -1149,11 +1153,6 @@ void ResXMLTree::uninit() restart(); } -const ResStringPool& ResXMLTree::getStrings() const -{ - return mStrings; -} - status_t ResXMLTree::validateNode(const ResXMLTree_node* node) const { const uint16_t eventCode = dtohs(node->header.type); diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index e586869..618f239 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -113,9 +113,6 @@ public class AudioService extends IAudioService.Stub { private Object mSettingsLock = new Object(); private boolean mMediaServerOk; - /** cached value of the BT dock address to recognize undocking events */ - private static String sBtDockAddress = ""; - private SoundPool mSoundPool; private Object mSoundEffectsLock = new Object(); private static final int NUM_SOUNDPOOL_CHANNELS = 4; @@ -269,6 +266,7 @@ public class AudioService extends IAudioService.Stub { new IntentFilter(Intent.ACTION_HEADSET_PLUG); intentFilter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED); intentFilter.addAction(BluetoothHeadset.ACTION_STATE_CHANGED); + intentFilter.addAction(Intent.ACTION_DOCK_EVENT); context.registerReceiver(mReceiver, intentFilter); } @@ -1498,7 +1496,23 @@ public class AudioService extends IAudioService.Stub { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) { + if (action.equals(Intent.ACTION_DOCK_EVENT)) { + int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, + Intent.EXTRA_DOCK_STATE_UNDOCKED); + int config; + switch (dockState) { + case Intent.EXTRA_DOCK_STATE_DESK: + config = AudioSystem.FORCE_BT_DESK_DOCK; + break; + case Intent.EXTRA_DOCK_STATE_CAR: + config = AudioSystem.FORCE_BT_CAR_DOCK; + break; + case Intent.EXTRA_DOCK_STATE_UNDOCKED: + default: + config = AudioSystem.FORCE_NONE; + } + AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); + } else if (action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) { int state = intent.getIntExtra(BluetoothA2dp.EXTRA_SINK_STATE, BluetoothA2dp.STATE_DISCONNECTED); BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); @@ -1508,10 +1522,6 @@ public class AudioService extends IAudioService.Stub { if (isConnected && state != BluetoothA2dp.STATE_CONNECTED && state != BluetoothA2dp.STATE_PLAYING) { - if (address.equals(sBtDockAddress)) { - Log.v(TAG, "Recognized undocking from BT dock"); - AudioSystem.setForceUse(AudioSystem.FOR_DOCK, AudioSystem.FORCE_NONE); - } AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, AudioSystem.DEVICE_STATE_UNAVAILABLE, address); @@ -1519,27 +1529,6 @@ public class AudioService extends IAudioService.Stub { } else if (!isConnected && (state == BluetoothA2dp.STATE_CONNECTED || state == BluetoothA2dp.STATE_PLAYING)) { - if (btDevice.isBluetoothDock()) { - Log.v(TAG, "Recognized connection to BT dock"); - sBtDockAddress = address; - Intent i = context.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT)); - if (i != null) { - int dockState = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED); - int config; - switch (dockState) { - case Intent.EXTRA_DOCK_STATE_DESK: - config = AudioSystem.FORCE_BT_DESK_DOCK; - break; - case Intent.EXTRA_DOCK_STATE_CAR: - config = AudioSystem.FORCE_BT_CAR_DOCK; - break; - case Intent.EXTRA_DOCK_STATE_UNDOCKED: - default: - config = AudioSystem.FORCE_NONE; - } - AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); - } - } AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, AudioSystem.DEVICE_STATE_AVAILABLE, address); diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index 1f02608..1047fa4 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -630,13 +630,9 @@ public class MediaScanner map.put(Video.Media.ARTIST, (mArtist != null && mArtist.length() > 0 ? mArtist : MediaStore.UNKNOWN_STRING)); map.put(Video.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0 ? mAlbum : MediaStore.UNKNOWN_STRING)); map.put(Video.Media.DURATION, mDuration); - map.put(Video.Media.DATE_TAKEN, mLastModified * 1000); // FIXME - add RESOLUTION } else if (MediaFile.isImageFileType(mFileType)) { // FIXME - add DESCRIPTION - // DATE_TAKEN will be overridden later if this is a JPEG image whose EXIF data - // contains date time information. - map.put(Images.Media.DATE_TAKEN, mLastModified * 1000); } else if (MediaFile.isAudioFileType(mFileType)) { map.put(Audio.Media.ARTIST, (mArtist != null && mArtist.length() > 0 ? mArtist : MediaStore.UNKNOWN_STRING)); map.put(Audio.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0 ? mAlbum : MediaStore.UNKNOWN_STRING)); diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index d2cec0c..f623295 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -104,7 +104,8 @@ status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player) { // scope for the lock Mutex::Autolock _l(mLock); - if ( !( mCurrentState & ( MEDIA_PLAYER_IDLE | MEDIA_PLAYER_STATE_ERROR ) ) ) { + if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) || + (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) { LOGE("setDataSource called in state %d", mCurrentState); return INVALID_OPERATION; } diff --git a/packages/SettingsProvider/etc/Android.mk b/packages/SettingsProvider/etc/Android.mk deleted file mode 100644 index 81ca4b1..0000000 --- a/packages/SettingsProvider/etc/Android.mk +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (C) 2008 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(my-dir) - -######################## -include $(CLEAR_VARS) - -LOCAL_MODULE := bookmarks.xml - -LOCAL_MODULE_TAGS := user - -# This will install the file in /system/etc -# -LOCAL_MODULE_CLASS := ETC - -LOCAL_SRC_FILES := $(LOCAL_MODULE) - -include $(BUILD_PREBUILT) - diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index bd131e0..64bb0ef 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -70,4 +70,7 @@ <string name="def_lock_sound" translatable="false">/system/media/audio/ui/Lock.ogg</string> <string name="def_unlock_sound" translatable="false">/system/media/audio/ui/Unlock.ogg</string> + <!-- Default for Settings.System.VIBRATE_IN_SILENT --> + <bool name="def_vibrate_in_silent">true</bool> + </resources> diff --git a/packages/SettingsProvider/etc/bookmarks.xml b/packages/SettingsProvider/res/xml/bookmarks.xml index 734e0cd..dfaeeaf 100644 --- a/packages/SettingsProvider/etc/bookmarks.xml +++ b/packages/SettingsProvider/res/xml/bookmarks.xml @@ -32,8 +32,8 @@ class="com.google.android.gm.ConversationListActivityGmail" shortcut="g" /> <bookmark - package="com.android.providers.im" - class="com.android.providers.im.LandingPage" + package="com.android.im" + class="com.android.im.app.LandingPage" shortcut="i" /> <bookmark package="com.android.calendar" @@ -53,8 +53,4 @@ package="com.android.mms" class="com.android.mms.ui.ConversationList" shortcut="s" /> - <bookmark - package="com.google.android.youtube" - class="com.google.android.youtube.HomeActivity" - shortcut="y" /> </bookmarks> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index bccf7d2..edf3923 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -23,40 +23,29 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.content.res.Resources; +import android.content.res.XmlResourceParser; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDoneException; -import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteStatement; import android.media.AudioManager; import android.media.AudioService; import android.net.ConnectivityManager; -import android.os.Environment; import android.os.SystemProperties; import android.provider.Settings; import android.provider.Settings.Secure; -import android.speech.RecognitionService; -import android.speech.RecognizerIntent; import android.text.TextUtils; +import android.util.AttributeSet; import android.util.Config; import android.util.Log; import android.util.Xml; import com.android.internal.telephony.RILConstants; import com.android.internal.util.XmlUtils; - import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternView; - import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; import java.util.List; @@ -65,11 +54,6 @@ import java.util.List; * Mostly just has a bit {@link #onCreate} to initialize the database. */ public class DatabaseHelper extends SQLiteOpenHelper { - /** - * Path to file containing default bookmarks, relative to ANDROID_ROOT. - */ - private static final String DEFAULT_BOOKMARKS_PATH = "etc/bookmarks.xml"; - private static final String TAG = "SettingsProvider"; private static final String DATABASE_NAME = "settings.db"; @@ -77,7 +61,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion' // is properly propagated through your change. Not doing so will result in a loss of user // settings. - private static final int DATABASE_VERSION = 52; + private static final int DATABASE_VERSION = 53; private Context mContext; @@ -158,7 +142,6 @@ public class DatabaseHelper extends SQLiteOpenHelper { * notification vibrate to on. */ loadVibrateSetting(db, true); - if (Config.LOGD) Log.d(TAG, "Reset system vibrate setting"); upgradeVersion = 21; } @@ -651,7 +634,26 @@ public class DatabaseHelper extends SQLiteOpenHelper { upgradeVersion = 52; } - if (upgradeVersion != currentVersion) { + if (upgradeVersion == 52) { + // new vibration/silent mode settings + db.beginTransaction(); + try { + SQLiteStatement stmt = db.compileStatement("INSERT INTO system(name,value)" + + " VALUES(?,?);"); + loadBooleanSetting(stmt, Settings.System.VIBRATE_IN_SILENT, + R.bool.def_vibrate_in_silent); + stmt.close(); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + upgradeVersion = 53; + } + + // *** Remember to update DATABASE_VERSION above! + + if (upgradeVersion != currentVersion) { Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion + ", must wipe the settings provider"); db.execSQL("DROP TABLE IF EXISTS system"); @@ -735,39 +737,28 @@ public class DatabaseHelper extends SQLiteOpenHelper { * * @param db The database to write the values into * @param startingIndex The zero-based position at which bookmarks in this file should begin - * @param subPath The relative path from ANDROID_ROOT to the file to read - * @param quiet If true, do no complain if the file is missing */ - private int loadBookmarks(SQLiteDatabase db, int startingIndex, String subPath, - boolean quiet) { - FileReader bookmarksReader; - - // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system". - final File favFile = new File(Environment.getRootDirectory(), subPath); - try { - bookmarksReader = new FileReader(favFile); - } catch (FileNotFoundException e) { - if (!quiet) { - Log.e(TAG, "Couldn't find or open bookmarks file " + favFile); - } - return 0; - } - + private int loadBookmarks(SQLiteDatabase db, int startingIndex) { Intent intent = new Intent(Intent.ACTION_MAIN, null); intent.addCategory(Intent.CATEGORY_LAUNCHER); ContentValues values = new ContentValues(); PackageManager packageManager = mContext.getPackageManager(); - ActivityInfo info; int i = startingIndex; - try { - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(bookmarksReader); + try { + XmlResourceParser parser = mContext.getResources().getXml(R.xml.bookmarks); XmlUtils.beginDocument(parser, "bookmarks"); - while (true) { - XmlUtils.nextElement(parser); + final int depth = parser.getDepth(); + int type; + + while (((type = parser.next()) != XmlPullParser.END_TAG || + parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { + + if (type != XmlPullParser.START_TAG) { + continue; + } String name = parser.getName(); if (!"bookmark".equals(name)) { @@ -777,23 +768,36 @@ public class DatabaseHelper extends SQLiteOpenHelper { String pkg = parser.getAttributeValue(null, "package"); String cls = parser.getAttributeValue(null, "class"); String shortcutStr = parser.getAttributeValue(null, "shortcut"); + int shortcutValue = (int) shortcutStr.charAt(0); if (TextUtils.isEmpty(shortcutStr)) { Log.w(TAG, "Unable to get shortcut for: " + pkg + "/" + cls); } + + ActivityInfo info = null; + ComponentName cn = new ComponentName(pkg, cls); try { - ComponentName cn = new ComponentName(pkg, cls); info = packageManager.getActivityInfo(cn, 0); + } catch (PackageManager.NameNotFoundException e) { + String[] packages = packageManager.canonicalToCurrentPackageNames( + new String[] { pkg }); + cn = new ComponentName(packages[0], cls); + try { + info = packageManager.getActivityInfo(cn, 0); + } catch (PackageManager.NameNotFoundException e1) { + Log.w(TAG, "Unable to add bookmark: " + pkg + "/" + cls, e); + } + } + + if (info != null) { intent.setComponent(cn); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - values.put(Settings.Bookmarks.INTENT, intent.toURI()); + values.put(Settings.Bookmarks.INTENT, intent.toUri(0)); values.put(Settings.Bookmarks.TITLE, info.loadLabel(packageManager).toString()); values.put(Settings.Bookmarks.SHORTCUT, shortcutValue); db.insert("bookmarks", null, values); i++; - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Unable to add bookmark: " + pkg + "/" + cls, e); } } } catch (XmlPullParserException e) { @@ -811,7 +815,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { * @param db The database to write the values into */ private void loadBookmarks(SQLiteDatabase db) { - loadBookmarks(db, 0, DEFAULT_BOOKMARKS_PATH, false); + loadBookmarks(db, 0); } /** @@ -890,8 +894,6 @@ public class DatabaseHelper extends SQLiteOpenHelper { SQLiteStatement stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)" + " VALUES(?,?);"); - Resources r = mContext.getResources(); - loadBooleanSetting(stmt, Settings.System.DIM_SCREEN, R.bool.def_dim_screen); loadSetting(stmt, Settings.System.STAY_ON_WHILE_PLUGGED_IN, @@ -947,6 +949,9 @@ public class DatabaseHelper extends SQLiteOpenHelper { loadUISoundEffectsSettings(stmt); + loadBooleanSetting(stmt, Settings.System.VIBRATE_IN_SILENT, + R.bool.def_vibrate_in_silent); + stmt.close(); } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 942d32d..1b4ba81 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -60,6 +60,11 @@ public class SettingsProvider extends ContentProvider { private static final SettingsCache sSystemCache = new SettingsCache(); private static final SettingsCache sSecureCache = new SettingsCache(); + // Over this size we don't reject loading or saving settings but + // we do consider them broken/malicious and don't keep them in + // memory at least: + private static final int MAX_CACHE_ENTRY_SIZE = 500; + private static final Bundle NULL_SETTING = Bundle.forPair("value", null); protected DatabaseHelper mOpenHelper; @@ -264,10 +269,7 @@ public class SettingsProvider extends ContentProvider { null, null, null, null); if (cursor != null && cursor.getCount() == 1) { cursor.moveToFirst(); - String value = cursor.getString(0); - Bundle bundle = (value == null) ? NULL_SETTING : Bundle.forPair("value", value); - cache.putIfAbsentLocked(key, bundle); - return bundle; + return cache.putIfAbsent(key, cursor.getString(0)); } } catch (SQLiteException e) { Log.w(TAG, "settings lookup error", e); @@ -275,7 +277,7 @@ public class SettingsProvider extends ContentProvider { } finally { if (cursor != null) cursor.close(); } - cache.putIfAbsentLocked(key, NULL_SETTING); + cache.putIfAbsent(key, null); return NULL_SETTING; } @@ -434,11 +436,16 @@ public class SettingsProvider extends ContentProvider { if (!parseProviderList(url, initialValues)) return null; } + SettingsCache cache = SettingsCache.forTable(args.table); + String value = initialValues.getAsString(Settings.NameValueTable.VALUE); + if (SettingsCache.isRedundantSetValue(cache, name, value)) { + return Uri.withAppendedPath(url, name); + } + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); final long rowId = db.insert(args.table, null, initialValues); if (rowId <= 0) return null; - SettingsCache cache = SettingsCache.forTable(args.table); SettingsCache.populate(cache, initialValues); // before we notify if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + initialValues); @@ -592,6 +599,7 @@ public class SettingsProvider extends ContentProvider { * database. */ private static final class SettingsCache extends LinkedHashMap<String, Bundle> { + public SettingsCache() { super(MAX_CACHE_ENTRIES, 0.75f /* load factor */, true /* access ordered */); } @@ -601,14 +609,23 @@ public class SettingsProvider extends ContentProvider { return size() > MAX_CACHE_ENTRIES; } - public void putIfAbsentLocked(String key, Bundle value) { - synchronized (this) { - if (containsKey(key)) { - // Lost a race. - return; + /** + * Atomic cache population, conditional on size of value and if + * we lost a race. + * + * @returns a Bundle to send back to the client from call(), even + * if we lost the race. + */ + public Bundle putIfAbsent(String key, String value) { + Bundle bundle = (value == null) ? NULL_SETTING : Bundle.forPair("value", value); + if (value == null || value.length() <= MAX_CACHE_ENTRY_SIZE) { + synchronized (this) { + if (!containsKey(key)) { + put(key, bundle); + } } - put(key, value); } + return bundle; } public static SettingsCache forTable(String tableName) { @@ -635,7 +652,11 @@ public class SettingsProvider extends ContentProvider { } String value = contentValues.getAsString(Settings.NameValueTable.VALUE); synchronized (cache) { - cache.put(name, Bundle.forPair(Settings.NameValueTable.VALUE, value)); + if (value == null || value.length() <= MAX_CACHE_ENTRY_SIZE) { + cache.put(name, Bundle.forPair(Settings.NameValueTable.VALUE, value)); + } else { + cache.remove(name); + } } } @@ -653,5 +674,21 @@ public class SettingsProvider extends ContentProvider { } } + /** + * For suppressing duplicate/redundant settings inserts early, + * checking our cache first (but without faulting it in), + * before going to sqlite with the mutation. + */ + public static boolean isRedundantSetValue(SettingsCache cache, String name, String value) { + if (cache == null) return false; + synchronized (cache) { + Bundle bundle = cache.get(name); + if (bundle == null) return false; + String oldValue = bundle.getPairValue(); + if (oldValue == null && value == null) return true; + if ((oldValue == null) != (value == null)) return false; + return oldValue.equals(value); + } + } } } diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index a1c45dc..70deb3e 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -995,6 +995,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } else { newNet.reconnect(); + newNet = null; // not officially avail.. try anyway, but + // report no failover } } } diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index 0974f7f..713358d 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -26,6 +26,7 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.os.storage.IMountService; import android.os.storage.IMountServiceListener; +import android.os.storage.IMountShutdownObserver; import android.os.storage.StorageResultCode; import android.os.Handler; import android.os.Message; @@ -172,69 +173,110 @@ class MountService extends IMountService.Stub } } + class ShutdownCallBack extends UnmountCallBack { + IMountShutdownObserver observer; + ShutdownCallBack(String path, IMountShutdownObserver observer) { + super(path, true); + this.observer = observer; + } + + @Override + void handleFinished() { + int ret = doUnmountVolume(path, true); + if (observer != null) { + try { + observer.onShutDownComplete(ret); + } catch (RemoteException e) { + Log.w(TAG, "RemoteException when shutting down"); + } + } + } + } + final private Handler mHandler = new Handler() { ArrayList<UnmountCallBack> mForceUnmounts = new ArrayList<UnmountCallBack>(); + boolean mRegistered = false; + + void registerReceiver() { + mRegistered = true; + mContext.registerReceiver(mPmReceiver, mPmFilter); + } + + void unregisterReceiver() { + mRegistered = false; + mContext.unregisterReceiver(mPmReceiver); + } public void handleMessage(Message msg) { switch (msg.what) { case H_UNMOUNT_PM_UPDATE: { UnmountCallBack ucb = (UnmountCallBack) msg.obj; mForceUnmounts.add(ucb); - mContext.registerReceiver(mPmReceiver, mPmFilter); - boolean hasExtPkgs = mPms.updateExternalMediaStatus(false); - if (!hasExtPkgs) { - // Unregister right away - mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE); + // Register only if needed. + if (!mRegistered) { + registerReceiver(); + boolean hasExtPkgs = mPms.updateExternalMediaStatus(false); + if (!hasExtPkgs) { + // Unregister right away + mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE); + } } break; } case H_UNMOUNT_PM_DONE: { - // Unregister receiver - mContext.unregisterReceiver(mPmReceiver); - UnmountCallBack ucb = mForceUnmounts.get(0); - if (ucb == null || ucb.path == null) { - // Just ignore - return; + // Unregister now. + if (mRegistered) { + unregisterReceiver(); } - String path = ucb.path; - boolean done = false; - if (!ucb.force) { - done = true; - } else { - int pids[] = getStorageUsers(path); - if (pids == null || pids.length == 0) { + int size = mForceUnmounts.size(); + int sizeArr[] = new int[size]; + int sizeArrN = 0; + for (int i = 0; i < size; i++) { + UnmountCallBack ucb = mForceUnmounts.get(i); + String path = ucb.path; + boolean done = false; + if (!ucb.force) { done = true; } else { - // Kill processes holding references first - ActivityManagerService ams = (ActivityManagerService) - ServiceManager.getService("activity"); - // Eliminate system process here? - boolean ret = ams.killPidsForMemory(pids); - if (ret) { - // Confirm if file references have been freed. - pids = getStorageUsers(path); - if (pids == null || pids.length == 0) { - done = true; + int pids[] = getStorageUsers(path); + if (pids == null || pids.length == 0) { + done = true; + } else { + // Kill processes holding references first + ActivityManagerService ams = (ActivityManagerService) + ServiceManager.getService("activity"); + // Eliminate system process here? + boolean ret = ams.killPidsForMemory(pids); + if (ret) { + // Confirm if file references have been freed. + pids = getStorageUsers(path); + if (pids == null || pids.length == 0) { + done = true; + } } } } - } - if (done) { - mForceUnmounts.remove(0); - mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_MS, - ucb)); - } else { - if (ucb.retries >= MAX_UNMOUNT_RETRIES) { - Log.i(TAG, "Cannot unmount inspite of " + - MAX_UNMOUNT_RETRIES + " to unmount media"); - // Send final broadcast indicating failure to unmount. + if (done) { + sizeArr[sizeArrN++] = i; + mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_MS, + ucb)); } else { - mHandler.sendMessageDelayed( - mHandler.obtainMessage(H_UNMOUNT_PM_DONE, - ucb.retries++), - RETRY_UNMOUNT_DELAY); + if (ucb.retries >= MAX_UNMOUNT_RETRIES) { + Log.i(TAG, "Cannot unmount inspite of " + + MAX_UNMOUNT_RETRIES + " to unmount media"); + // Send final broadcast indicating failure to unmount. + } else { + mHandler.sendMessageDelayed( + mHandler.obtainMessage(H_UNMOUNT_PM_DONE, + ucb.retries++), + RETRY_UNMOUNT_DELAY); + } } } + // Remove already processed elements from list. + for (int i = (sizeArrN-1); i >= 0; i--) { + mForceUnmounts.remove(sizeArr[i]); + } break; } case H_UNMOUNT_MS : { @@ -826,7 +868,7 @@ class MountService extends IMountService.Stub } } - public void shutdown() { + public void shutdown(final IMountShutdownObserver observer) { validatePermission(android.Manifest.permission.SHUTDOWN); Log.i(TAG, "Shutting down"); @@ -865,12 +907,9 @@ class MountService extends IMountService.Stub } if (state.equals(Environment.MEDIA_MOUNTED)) { - /* - * If the media is mounted, then gracefully unmount it. - */ - if (doUnmountVolume(path, true) != StorageResultCode.OperationSucceeded) { - Log.e(TAG, "Failed to unmount media for shutdown"); - } + // Post a unmount message. + ShutdownCallBack ucb = new ShutdownCallBack(path, observer); + mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb)); } } diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 371fa37..4c1356b 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -4589,7 +4589,7 @@ class PackageManagerService extends IPackageManager.Stub { } else { // When replacing apps make sure we honour // the existing app location if not overwritten by other options - boolean prevOnSd = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0; + boolean prevOnSd = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; if (onSd) { // Install flag overrides everything. return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; @@ -5995,7 +5995,7 @@ class PackageManagerService extends IPackageManager.Stub { // Delete application code and resources if (deleteCodeAndResources) { // TODO can pick up from PackageSettings as well - int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD)!=0) ? + int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE)!=0) ? PackageManager.INSTALL_EXTERNAL : 0; installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ? PackageManager.INSTALL_FORWARD_LOCK : 0; @@ -7214,7 +7214,7 @@ class PackageManagerService extends IPackageManager.Stub { void setFlags(int pkgFlags) { this.pkgFlags = (pkgFlags & ApplicationInfo.FLAG_SYSTEM) | (pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) | - (pkgFlags & ApplicationInfo.FLAG_ON_SDCARD) | + (pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) | (pkgFlags & ApplicationInfo.FLAG_NEVER_ENCRYPT); } } @@ -9058,7 +9058,7 @@ class PackageManagerService extends IPackageManager.Stub { return false; } mMediaMounted = mediaStatus; - Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_ON_SDCARD); + Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_EXTERNAL_STORAGE); ret = appList != null && appList.size() > 0; } // Queue up an async operation since the package installation may take a little while. @@ -9107,7 +9107,7 @@ class PackageManagerService extends IPackageManager.Stub { if (DEBUG_SD_INSTALL) Log.i(TAG, "Looking for pkg : " + pkgName); PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps != null && ps.codePathString != null && - (ps.pkgFlags & ApplicationInfo.FLAG_ON_SDCARD) != 0) { + (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) { if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " corresponds to pkg : " + pkgName + " at code path: " + ps.codePathString); @@ -9333,7 +9333,7 @@ class PackageManagerService extends IPackageManager.Stub { } else { newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ? PackageManager.INSTALL_EXTERNAL : 0; - currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0 ? + currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 ? PackageManager.INSTALL_EXTERNAL : 0; if (newFlags == currFlags) { Log.w(TAG, "No move required. Trying to move to same location"); @@ -9400,9 +9400,9 @@ class PackageManagerService extends IPackageManager.Stub { ps.resourcePathString = ps.resourcePath.getPath(); // Set the application info flag correctly. if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) { - pkg.applicationInfo.flags |= ApplicationInfo.FLAG_ON_SDCARD; + pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE; } else { - pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_ON_SDCARD; + pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE; } ps.setFlags(pkg.applicationInfo.flags); mAppDirs.remove(oldCodePath); diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 0189c60..fc6bfcd 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -17,6 +17,7 @@ package com.android.server; import com.android.internal.app.IBatteryStats; +import com.android.internal.app.ShutdownThread; import com.android.server.am.BatteryStatsService; import android.app.ActivityManagerNative; @@ -41,7 +42,6 @@ import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; -import android.os.storage.IMountService; import android.os.IPowerManager; import android.os.LocalPowerManager; import android.os.Power; @@ -2202,28 +2202,35 @@ class PowerManagerService extends IPowerManager.Stub { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null); - /* - * Manually shutdown the MountService to ensure media is - * put into a safe state. - */ - IMountService mSvc = IMountService.Stub.asInterface( - ServiceManager.getService("mount")); + if (mHandler == null || !ActivityManagerNative.isSystemReady()) { + throw new IllegalStateException("Too early to call reboot()"); + } + + final String finalReason = reason; + Runnable runnable = new Runnable() { + public void run() { + synchronized (this) { + ShutdownThread.reboot(mContext, finalReason, false); + // if we get here we failed + notify(); + } + + } + }; + + mHandler.post(runnable); - if (mSvc != null) { + // block until we reboot or fail. + // throw an exception if we failed to reboot + synchronized (runnable) { try { - mSvc.shutdown(); - } catch (Exception e) { - Slog.e(TAG, "MountService shutdown failed", e); + runnable.wait(); + } catch (InterruptedException e) { } - } else { - Slog.w(TAG, "MountService unavailable for shutdown"); - } - - try { - Power.reboot(reason); - } catch (IOException e) { - Slog.e(TAG, "reboot failed", e); } + + // if we get here we failed + throw new IllegalStateException("unable to reboot!"); } /** diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java index f97f50a..3f64b25 100644 --- a/services/java/com/android/server/Watchdog.java +++ b/services/java/com/android/server/Watchdog.java @@ -29,6 +29,7 @@ import android.os.Debug; import android.os.Handler; import android.os.Message; import android.os.Process; +import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.provider.Settings; @@ -676,11 +677,8 @@ public class Watchdog extends Thread { */ void rebootSystem(String reason) { Slog.i(TAG, "Rebooting system because: " + reason); - try { - android.os.Power.reboot(reason); - } catch (IOException e) { - Slog.e(TAG, "Reboot failed!", e); - } + PowerManagerService pms = (PowerManagerService) ServiceManager.getService("power"); + pms.reboot(reason); } /** diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 8fa862d..62263a6 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -346,9 +346,8 @@ public class WifiService extends IWifiManager.Stub { */ public boolean pingSupplicant() { enforceChangePermission(); - synchronized (mWifiStateTracker) { - return WifiNative.pingCommand(); - } + + return mWifiStateTracker.ping(); } /** @@ -357,20 +356,19 @@ public class WifiService extends IWifiManager.Stub { */ public boolean startScan(boolean forceActive) { enforceChangePermission(); - synchronized (mWifiStateTracker) { - switch (mWifiStateTracker.getSupplicantState()) { - case DISCONNECTED: - case INACTIVE: - case SCANNING: - case DORMANT: - break; - default: - WifiNative.setScanResultHandlingCommand( - WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY); - break; - } - return WifiNative.scanCommand(forceActive); + + switch (mWifiStateTracker.getSupplicantState()) { + case DISCONNECTED: + case INACTIVE: + case SCANNING: + case DORMANT: + break; + default: + mWifiStateTracker.setScanResultHandling( + WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY); + break; } + return mWifiStateTracker.scan(forceActive); } /** @@ -434,19 +432,18 @@ public class WifiService extends IWifiManager.Stub { } if (enable) { - synchronized (mWifiStateTracker) { - if (!WifiNative.loadDriver()) { - Slog.e(TAG, "Failed to load Wi-Fi driver."); - setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); - return false; - } - if (!WifiNative.startSupplicant()) { - WifiNative.unloadDriver(); - Slog.e(TAG, "Failed to start supplicant daemon."); - setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); - return false; - } + if (!mWifiStateTracker.loadDriver()) { + Slog.e(TAG, "Failed to load Wi-Fi driver."); + setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); + return false; + } + if (!mWifiStateTracker.startSupplicant()) { + mWifiStateTracker.unloadDriver(); + Slog.e(TAG, "Failed to start supplicant daemon."); + setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); + return false; } + registerForBroadcasts(); mWifiStateTracker.startEventLoop(); } else { @@ -456,27 +453,27 @@ public class WifiService extends IWifiManager.Stub { mWifiStateTracker.setNotificationVisible(false, 0, false, 0); boolean failedToStopSupplicantOrUnloadDriver = false; - synchronized (mWifiStateTracker) { - if (!WifiNative.stopSupplicant()) { - Slog.e(TAG, "Failed to stop supplicant daemon."); - setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); - failedToStopSupplicantOrUnloadDriver = true; - } - /** - * Reset connections and disable interface - * before we unload the driver - */ - mWifiStateTracker.resetConnections(true); + if (!mWifiStateTracker.stopSupplicant()) { + Slog.e(TAG, "Failed to stop supplicant daemon."); + setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); + failedToStopSupplicantOrUnloadDriver = true; + } - if (!WifiNative.unloadDriver()) { - Slog.e(TAG, "Failed to unload Wi-Fi driver."); - if (!failedToStopSupplicantOrUnloadDriver) { - setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); - failedToStopSupplicantOrUnloadDriver = true; - } + /** + * Reset connections and disable interface + * before we unload the driver + */ + mWifiStateTracker.resetConnections(true); + + if (!mWifiStateTracker.unloadDriver()) { + Slog.e(TAG, "Failed to unload Wi-Fi driver."); + if (!failedToStopSupplicantOrUnloadDriver) { + setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); + failedToStopSupplicantOrUnloadDriver = true; } } + if (failedToStopSupplicantOrUnloadDriver) { return false; } @@ -553,9 +550,8 @@ public class WifiService extends IWifiManager.Stub { */ public boolean disconnect() { enforceChangePermission(); - synchronized (mWifiStateTracker) { - return WifiNative.disconnectCommand(); - } + + return mWifiStateTracker.disconnect(); } /** @@ -564,9 +560,8 @@ public class WifiService extends IWifiManager.Stub { */ public boolean reconnect() { enforceChangePermission(); - synchronized (mWifiStateTracker) { - return WifiNative.reconnectCommand(); - } + + return mWifiStateTracker.reconnectCommand(); } /** @@ -575,9 +570,8 @@ public class WifiService extends IWifiManager.Stub { */ public boolean reassociate() { enforceChangePermission(); - synchronized (mWifiStateTracker) { - return WifiNative.reassociateCommand(); - } + + return mWifiStateTracker.reassociate(); } private boolean getPersistedWifiApEnabled() { @@ -650,12 +644,10 @@ public class WifiService extends IWifiManager.Stub { } if (enable) { - synchronized (mWifiStateTracker) { - if (!WifiNative.loadDriver()) { - Slog.e(TAG, "Failed to load Wi-Fi driver for AP mode"); - setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid); - return false; - } + if (!mWifiStateTracker.loadDriver()) { + Slog.e(TAG, "Failed to load Wi-Fi driver for AP mode"); + setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid); + return false; } try { @@ -672,12 +664,10 @@ public class WifiService extends IWifiManager.Stub { Slog.e(TAG, "Exception in stopAccessPoint()"); } - synchronized (mWifiStateTracker) { - if (!WifiNative.unloadDriver()) { - Slog.e(TAG, "Failed to unload Wi-Fi driver for AP mode"); - setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid); - return false; - } + if (!mWifiStateTracker.unloadDriver()) { + Slog.e(TAG, "Failed to unload Wi-Fi driver for AP mode"); + setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid); + return false; } } @@ -735,15 +725,15 @@ public class WifiService extends IWifiManager.Stub { public List<WifiConfiguration> getConfiguredNetworks() { enforceAccessPermission(); String listStr; + /* * We don't cache the list, because we want to allow * for the possibility that the configuration file * has been modified through some external means, * such as the wpa_cli command line program. */ - synchronized (mWifiStateTracker) { - listStr = WifiNative.listNetworksCommand(); - } + listStr = mWifiStateTracker.listNetworks(); + List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>(); if (listStr == null) @@ -767,11 +757,10 @@ public class WifiService extends IWifiManager.Stub { config.status = WifiConfiguration.Status.DISABLED; else config.status = WifiConfiguration.Status.ENABLED; - } else + } else { config.status = WifiConfiguration.Status.ENABLED; - synchronized (mWifiStateTracker) { - readNetworkVariables(config); } + readNetworkVariables(config); networks.add(config); } @@ -785,7 +774,7 @@ public class WifiService extends IWifiManager.Stub { * The caller must hold the synchronization monitor. * @param config the {@link WifiConfiguration} object to be filled in. */ - private static void readNetworkVariables(WifiConfiguration config) { + private void readNetworkVariables(WifiConfiguration config) { int netId = config.networkId; if (netId < 0) @@ -798,21 +787,21 @@ public class WifiService extends IWifiManager.Stub { */ String value; - value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.ssidVarName); + value = mWifiStateTracker.getNetworkVariable(netId, WifiConfiguration.ssidVarName); if (!TextUtils.isEmpty(value)) { config.SSID = removeDoubleQuotes(value); } else { config.SSID = null; } - value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.bssidVarName); + value = mWifiStateTracker.getNetworkVariable(netId, WifiConfiguration.bssidVarName); if (!TextUtils.isEmpty(value)) { config.BSSID = value; } else { config.BSSID = null; } - value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.priorityVarName); + value = mWifiStateTracker.getNetworkVariable(netId, WifiConfiguration.priorityVarName); config.priority = -1; if (!TextUtils.isEmpty(value)) { try { @@ -821,7 +810,7 @@ public class WifiService extends IWifiManager.Stub { } } - value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.hiddenSSIDVarName); + value = mWifiStateTracker.getNetworkVariable(netId, WifiConfiguration.hiddenSSIDVarName); config.hiddenSSID = false; if (!TextUtils.isEmpty(value)) { try { @@ -830,7 +819,7 @@ public class WifiService extends IWifiManager.Stub { } } - value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.wepTxKeyIdxVarName); + value = mWifiStateTracker.getNetworkVariable(netId, WifiConfiguration.wepTxKeyIdxVarName); config.wepTxKeyIndex = -1; if (!TextUtils.isEmpty(value)) { try { @@ -844,7 +833,7 @@ public class WifiService extends IWifiManager.Stub { * just a "*" if the key is set, or the null string otherwise. */ for (int i = 0; i < 4; i++) { - value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.wepKeyVarNames[i]); + value = mWifiStateTracker.getNetworkVariable(netId, WifiConfiguration.wepKeyVarNames[i]); if (!TextUtils.isEmpty(value)) { config.wepKeys[i] = value; } else { @@ -856,14 +845,14 @@ public class WifiService extends IWifiManager.Stub { * Get the private shared key. Note that the actual keys are not passed back, * just a "*" if the key is set, or the null string otherwise. */ - value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.pskVarName); + value = mWifiStateTracker.getNetworkVariable(netId, WifiConfiguration.pskVarName); if (!TextUtils.isEmpty(value)) { config.preSharedKey = value; } else { config.preSharedKey = null; } - value = WifiNative.getNetworkVariableCommand(config.networkId, + value = mWifiStateTracker.getNetworkVariable(config.networkId, WifiConfiguration.Protocol.varName); if (!TextUtils.isEmpty(value)) { String vals[] = value.split(" "); @@ -876,7 +865,7 @@ public class WifiService extends IWifiManager.Stub { } } - value = WifiNative.getNetworkVariableCommand(config.networkId, + value = mWifiStateTracker.getNetworkVariable(config.networkId, WifiConfiguration.KeyMgmt.varName); if (!TextUtils.isEmpty(value)) { String vals[] = value.split(" "); @@ -889,7 +878,7 @@ public class WifiService extends IWifiManager.Stub { } } - value = WifiNative.getNetworkVariableCommand(config.networkId, + value = mWifiStateTracker.getNetworkVariable(config.networkId, WifiConfiguration.AuthAlgorithm.varName); if (!TextUtils.isEmpty(value)) { String vals[] = value.split(" "); @@ -902,7 +891,7 @@ public class WifiService extends IWifiManager.Stub { } } - value = WifiNative.getNetworkVariableCommand(config.networkId, + value = mWifiStateTracker.getNetworkVariable(config.networkId, WifiConfiguration.PairwiseCipher.varName); if (!TextUtils.isEmpty(value)) { String vals[] = value.split(" "); @@ -915,7 +904,7 @@ public class WifiService extends IWifiManager.Stub { } } - value = WifiNative.getNetworkVariableCommand(config.networkId, + value = mWifiStateTracker.getNetworkVariable(config.networkId, WifiConfiguration.GroupCipher.varName); if (!TextUtils.isEmpty(value)) { String vals[] = value.split(" "); @@ -930,7 +919,7 @@ public class WifiService extends IWifiManager.Stub { for (WifiConfiguration.EnterpriseField field : config.enterpriseFields) { - value = WifiNative.getNetworkVariableCommand(netId, + value = mWifiStateTracker.getNetworkVariable(netId, field.varName()); if (!TextUtils.isEmpty(value)) { if (field != config.eap) value = removeDoubleQuotes(value); @@ -955,6 +944,7 @@ public class WifiService extends IWifiManager.Stub { */ public int addOrUpdateNetwork(WifiConfiguration config) { enforceChangePermission(); + /* * If the supplied networkId is -1, we create a new empty * network configuration. Otherwise, the networkId should @@ -967,7 +957,7 @@ public class WifiService extends IWifiManager.Stub { // networkId of -1 means we want to create a new network synchronized (mWifiStateTracker) { if (newNetwork) { - netId = WifiNative.addNetworkCommand(); + netId = mWifiStateTracker.addNetwork(); if (netId < 0) { if (DBG) { Slog.d(TAG, "Failed to add a network!"); @@ -976,7 +966,8 @@ public class WifiService extends IWifiManager.Stub { } doReconfig = true; } else { - String priorityVal = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.priorityVarName); + String priorityVal = mWifiStateTracker.getNetworkVariable( + netId, WifiConfiguration.priorityVarName); currentPriority = -1; if (!TextUtils.isEmpty(priorityVal)) { try { @@ -987,16 +978,17 @@ public class WifiService extends IWifiManager.Stub { doReconfig = currentPriority != config.priority; } mNeedReconfig = mNeedReconfig || doReconfig; + } - setVariables: { + setVariables: { /* * Note that if a networkId for a non-existent network - * was supplied, then the first setNetworkVariableCommand() + * was supplied, then the first setNetworkVariable() * will fail, so we don't bother to make a separate check * for the validity of the ID up front. */ if (config.SSID != null && - !WifiNative.setNetworkVariableCommand( + !mWifiStateTracker.setNetworkVariable( netId, WifiConfiguration.ssidVarName, convertToQuotedString(config.SSID))) { @@ -1007,7 +999,7 @@ public class WifiService extends IWifiManager.Stub { } if (config.BSSID != null && - !WifiNative.setNetworkVariableCommand( + !mWifiStateTracker.setNetworkVariable( netId, WifiConfiguration.bssidVarName, config.BSSID)) { @@ -1020,7 +1012,7 @@ public class WifiService extends IWifiManager.Stub { String allowedKeyManagementString = makeString(config.allowedKeyManagement, WifiConfiguration.KeyMgmt.strings); if (config.allowedKeyManagement.cardinality() != 0 && - !WifiNative.setNetworkVariableCommand( + !mWifiStateTracker.setNetworkVariable( netId, WifiConfiguration.KeyMgmt.varName, allowedKeyManagementString)) { @@ -1034,7 +1026,7 @@ public class WifiService extends IWifiManager.Stub { String allowedProtocolsString = makeString(config.allowedProtocols, WifiConfiguration.Protocol.strings); if (config.allowedProtocols.cardinality() != 0 && - !WifiNative.setNetworkVariableCommand( + !mWifiStateTracker.setNetworkVariable( netId, WifiConfiguration.Protocol.varName, allowedProtocolsString)) { @@ -1048,7 +1040,7 @@ public class WifiService extends IWifiManager.Stub { String allowedAuthAlgorithmsString = makeString(config.allowedAuthAlgorithms, WifiConfiguration.AuthAlgorithm.strings); if (config.allowedAuthAlgorithms.cardinality() != 0 && - !WifiNative.setNetworkVariableCommand( + !mWifiStateTracker.setNetworkVariable( netId, WifiConfiguration.AuthAlgorithm.varName, allowedAuthAlgorithmsString)) { @@ -1062,7 +1054,7 @@ public class WifiService extends IWifiManager.Stub { String allowedPairwiseCiphersString = makeString(config.allowedPairwiseCiphers, WifiConfiguration.PairwiseCipher.strings); if (config.allowedPairwiseCiphers.cardinality() != 0 && - !WifiNative.setNetworkVariableCommand( + !mWifiStateTracker.setNetworkVariable( netId, WifiConfiguration.PairwiseCipher.varName, allowedPairwiseCiphersString)) { @@ -1076,7 +1068,7 @@ public class WifiService extends IWifiManager.Stub { String allowedGroupCiphersString = makeString(config.allowedGroupCiphers, WifiConfiguration.GroupCipher.strings); if (config.allowedGroupCiphers.cardinality() != 0 && - !WifiNative.setNetworkVariableCommand( + !mWifiStateTracker.setNetworkVariable( netId, WifiConfiguration.GroupCipher.varName, allowedGroupCiphersString)) { @@ -1090,7 +1082,7 @@ public class WifiService extends IWifiManager.Stub { // Prevent client screw-up by passing in a WifiConfiguration we gave it // by preventing "*" as a key. if (config.preSharedKey != null && !config.preSharedKey.equals("*") && - !WifiNative.setNetworkVariableCommand( + !mWifiStateTracker.setNetworkVariable( netId, WifiConfiguration.pskVarName, config.preSharedKey)) { @@ -1106,7 +1098,7 @@ public class WifiService extends IWifiManager.Stub { // Prevent client screw-up by passing in a WifiConfiguration we gave it // by preventing "*" as a key. if (config.wepKeys[i] != null && !config.wepKeys[i].equals("*")) { - if (!WifiNative.setNetworkVariableCommand( + if (!mWifiStateTracker.setNetworkVariable( netId, WifiConfiguration.wepKeyVarNames[i], config.wepKeys[i])) { @@ -1123,7 +1115,7 @@ public class WifiService extends IWifiManager.Stub { } if (hasSetKey) { - if (!WifiNative.setNetworkVariableCommand( + if (!mWifiStateTracker.setNetworkVariable( netId, WifiConfiguration.wepTxKeyIdxVarName, Integer.toString(config.wepTxKeyIndex))) { @@ -1136,7 +1128,7 @@ public class WifiService extends IWifiManager.Stub { } } - if (!WifiNative.setNetworkVariableCommand( + if (!mWifiStateTracker.setNetworkVariable( netId, WifiConfiguration.priorityVarName, Integer.toString(config.priority))) { @@ -1147,7 +1139,7 @@ public class WifiService extends IWifiManager.Stub { break setVariables; } - if (config.hiddenSSID && !WifiNative.setNetworkVariableCommand( + if (config.hiddenSSID && !mWifiStateTracker.setNetworkVariable( netId, WifiConfiguration.hiddenSSIDVarName, Integer.toString(config.hiddenSSID ? 1 : 0))) { @@ -1166,7 +1158,7 @@ public class WifiService extends IWifiManager.Stub { if (field != config.eap) { value = (value.length() == 0) ? "NULL" : convertToQuotedString(value); } - if (!WifiNative.setNetworkVariableCommand( + if (!mWifiStateTracker.setNetworkVariable( netId, varName, value)) { @@ -1179,21 +1171,20 @@ public class WifiService extends IWifiManager.Stub { } } return netId; - } + } - /* - * For an update, if one of the setNetworkVariable operations fails, - * we might want to roll back all the changes already made. But the - * chances are that if anything is going to go wrong, it'll happen - * the first time we try to set one of the variables. - */ - if (newNetwork) { - removeNetwork(netId); - if (DBG) { - Slog.d(TAG, - "Failed to set a network variable, removed network: " - + netId); - } + /* + * For an update, if one of the setNetworkVariable operations fails, + * we might want to roll back all the changes already made. But the + * chances are that if anything is going to go wrong, it'll happen + * the first time we try to set one of the variables. + */ + if (newNetwork) { + removeNetwork(netId); + if (DBG) { + Slog.d(TAG, + "Failed to set a network variable, removed network: " + + netId); } } return -1; @@ -1260,15 +1251,13 @@ public class WifiService extends IWifiManager.Stub { public boolean enableNetwork(int netId, boolean disableOthers) { enforceChangePermission(); - synchronized (mWifiStateTracker) { - String ifname = mWifiStateTracker.getInterfaceName(); - NetworkUtils.enableInterface(ifname); - boolean result = WifiNative.enableNetworkCommand(netId, disableOthers); - if (!result) { - NetworkUtils.disableInterface(ifname); - } - return result; + String ifname = mWifiStateTracker.getInterfaceName(); + NetworkUtils.enableInterface(ifname); + boolean result = mWifiStateTracker.enableNetwork(netId, disableOthers); + if (!result) { + NetworkUtils.disableInterface(ifname); } + return result; } /** @@ -1280,9 +1269,7 @@ public class WifiService extends IWifiManager.Stub { public boolean disableNetwork(int netId) { enforceChangePermission(); - synchronized (mWifiStateTracker) { - return WifiNative.disableNetworkCommand(netId); - } + return mWifiStateTracker.disableNetwork(netId); } /** @@ -1306,9 +1293,8 @@ public class WifiService extends IWifiManager.Stub { public List<ScanResult> getScanResults() { enforceAccessPermission(); String reply; - synchronized (mWifiStateTracker) { - reply = WifiNative.scanResultsCommand(); - } + + reply = mWifiStateTracker.scanResults(); if (reply == null) { return null; } @@ -1456,11 +1442,12 @@ public class WifiService extends IWifiManager.Stub { public boolean saveConfiguration() { boolean result; enforceChangePermission(); + synchronized (mWifiStateTracker) { - result = WifiNative.saveConfigCommand(); + result = mWifiStateTracker.saveConfig(); if (result && mNeedReconfig) { mNeedReconfig = false; - result = WifiNative.reloadConfigCommand(); + result = mWifiStateTracker.reloadConfig(); if (result) { Intent intent = new Intent(WifiManager.NETWORK_IDS_CHANGED_ACTION); @@ -1532,18 +1519,17 @@ public class WifiService extends IWifiManager.Stub { int numChannels; enforceAccessPermission(); - synchronized (mWifiStateTracker) { - /* - * If we can't get the value from the driver (e.g., because - * Wi-Fi is not currently enabled), get the value from - * Settings. - */ - numChannels = WifiNative.getNumAllowedChannelsCommand(); - if (numChannels < 0) { - numChannels = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS, - -1); - } + + /* + * If we can't get the value from the driver (e.g., because + * Wi-Fi is not currently enabled), get the value from + * Settings. + */ + numChannels = mWifiStateTracker.getNumAllowedChannels(); + if (numChannels < 0) { + numChannels = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS, + -1); } return numChannels; } @@ -2126,14 +2112,13 @@ public class WifiService extends IWifiManager.Stub { public void initializeMulticastFiltering() { enforceMulticastChangePermission(); + synchronized (mMulticasters) { // if anybody had requested filters be off, leave off if (mMulticasters.size() != 0) { return; } else { - synchronized (mWifiStateTracker) { - WifiNative.startPacketFiltering(); - } + mWifiStateTracker.startPacketFiltering(); } } } @@ -2148,9 +2133,7 @@ public class WifiService extends IWifiManager.Stub { // our new size == 1 (first call), but this function won't // be called often and by making the stopPacket call each // time we're less fragile and self-healing. - synchronized (mWifiStateTracker) { - WifiNative.stopPacketFiltering(); - } + mWifiStateTracker.stopPacketFiltering(); } int uid = Binder.getCallingUid(); @@ -2182,13 +2165,12 @@ public class WifiService extends IWifiManager.Stub { private void removeMulticasterLocked(int i, int uid) { Multicaster removed = mMulticasters.remove(i); + if (removed != null) { removed.unlinkDeathRecipient(); } if (mMulticasters.size() == 0) { - synchronized (mWifiStateTracker) { - WifiNative.startPacketFiltering(); - } + mWifiStateTracker.startPacketFiltering(); } Long ident = Binder.clearCallingIdentity(); diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index f5d3e8e..34a7fc0 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -10267,9 +10267,10 @@ public class WindowManagerService extends IWindowManager.Stub && buttonBrightness < 0) { buttonBrightness = w.mAttrs.buttonBrightness; } - if (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG - || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD - || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR) { + if (canBeSeen + && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG + || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD + || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) { syswin = true; } } diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index 78329db..e52cd47 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -54,14 +54,12 @@ import java.util.Set; * @hide * * Timeout - * TODO - review error states - they currently are dead-ends with no recovery possible * * TODO - look for parent classes and code sharing */ public class Tethering extends INetworkManagementEventObserver.Stub { - private Notification mTetheringNotification; private Context mContext; private final String TAG = "Tethering"; @@ -92,7 +90,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private boolean mUseHiPri; private String mUpstreamIfaceName; - HierarchicalStateMachine mTetherMasterSM; + private HierarchicalStateMachine mTetherMasterSM; + + private Notification mTetheredNotification; public Tethering(Context context) { Log.d(TAG, "Tethering starting"); @@ -152,18 +152,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link); boolean found = false; boolean usb = false; - for (String regex : mTetherableWifiRegexs) { - if (iface.matches(regex)) { - found = true; - break; - } - } - for (String regex: mTetherableUsbRegexs) { - if (iface.matches(regex)) { - found = true; - usb = true; - break; - } + if (isWifi(iface)) { + found = true; + } else if (isUsb(iface)) { + found = true; + usb = true; } if (found == false) return; @@ -184,23 +177,31 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } } + private boolean isUsb(String iface) { + for (String regex : mTetherableUsbRegexs) { + if (iface.matches(regex)) return true; + } + return false; + } + + public boolean isWifi(String iface) { + for (String regex : mTetherableWifiRegexs) { + if (iface.matches(regex)) return true; + } + return false; + } + 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; - break; - } + if (isWifi(iface)) { + found = true; } - for (String regex : mTetherableUsbRegexs) { - if (iface.matches(regex)) { - found = true; - usb = true; - break; - } + if (isUsb(iface)) { + found = true; + usb = true; } if (found == false) { Log.d(TAG, iface + " is not a tetherable iface, ignoring"); @@ -293,6 +294,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub { ArrayList<String> activeList = new ArrayList<String>(); ArrayList<String> erroredList = new ArrayList<String>(); + boolean wifiTethered = false; + boolean usbTethered = false; + synchronized (mIfaces) { Set ifaces = mIfaces.keySet(); for (Object iface : ifaces) { @@ -303,6 +307,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } else if (sm.isAvailable()) { availableList.add((String)iface); } else if (sm.isTethered()) { + if (isUsb((String)iface)) { + usbTethered = true; + } else if (isWifi((String)iface)) { + wifiTethered = true; + } activeList.add((String)iface); } } @@ -318,6 +327,58 @@ public class Tethering extends INetworkManagementEventObserver.Stub { mContext.sendStickyBroadcast(broadcast); Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " + activeList.size() + ", " + erroredList.size()); + + if (usbTethered) { + if (wifiTethered) { + showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general); + } else { + showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb); + } + } else if (wifiTethered) { + showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi); + } else { + clearTetheredNotification(); + } + } + + private void showTetheredNotification(int icon) { + NotificationManager notificationManager = + (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); + if (notificationManager == null) { + return; + } + + Intent intent = new Intent(); + intent.setClassName("com.android.settings", "com.android.settings.TetherSettings"); + intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); + + PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0); + + Resources r = Resources.getSystem(); + CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title); + CharSequence message = r.getText(com.android.internal.R.string. + tethered_notification_message); + + if(mTetheredNotification == null) { + mTetheredNotification = new Notification(); + mTetheredNotification.when = 0; + } + mTetheredNotification.icon = icon; + mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND; + mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT; + mTetheredNotification.tickerText = title; + mTetheredNotification.setLatestEventInfo(mContext, title, message, pi); + + notificationManager.notify(mTetheredNotification.icon, mTetheredNotification); + } + + private void clearTetheredNotification() { + NotificationManager notificationManager = + (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); + if (notificationManager != null && mTetheredNotification != null) { + notificationManager.cancel(mTetheredNotification.icon); + mTetheredNotification = null; + } } private class StateReceiver extends BroadcastReceiver { @@ -367,13 +428,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return; } for (String iface : ifaces) { - for (String regex : mTetherableUsbRegexs) { - if (iface.matches(regex)) { - if (enable) { - interfaceAdded(iface); - } else { - interfaceRemoved(iface); - } + if (isUsb(iface)) { + if (enable) { + interfaceAdded(iface); + } else { + interfaceRemoved(iface); } } } @@ -420,27 +479,25 @@ public class Tethering extends INetworkManagementEventObserver.Stub { 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"); - } - ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", ""); - ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," "); - service.setInterfaceConfig(iface, ifcg); + if (isUsb(iface)) { + 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"); } - } catch (Exception e) { - Log.e(TAG, "Error configuring interface " + iface + ", :" + e); - return false; + ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", ""); + ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," "); + service.setInterfaceConfig(iface, ifcg); } + } catch (Exception e) { + Log.e(TAG, "Error configuring interface " + iface + ", :" + e); + return false; } } } diff --git a/tests/AndroidTests/AndroidManifest.xml b/tests/AndroidTests/AndroidManifest.xml index e06c3a8..1f0bf4d 100644 --- a/tests/AndroidTests/AndroidManifest.xml +++ b/tests/AndroidTests/AndroidManifest.xml @@ -35,6 +35,7 @@ <uses-permission android:name="android.permission.ASEC_DESTROY" /> <uses-permission android:name="android.permission.ASEC_MOUNT_UNMOUNT" /> <uses-permission android:name="android.permission.ASEC_RENAME" /> + <uses-permission android:name="android.permission.SHUTDOWN" /> <uses-permission android:name="com.android.unit_tests.permission.TEST_GRANTED" /> <uses-permission android:name="com.google.android.googleapps.permission.ACCESS_GOOGLE_PASSWORD" /> <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" /> diff --git a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java index c7bacd4..9aed363 100755 --- a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java +++ b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java @@ -16,6 +16,8 @@ package com.android.unit_tests; +import com.android.unit_tests.PackageManagerTests.StorageListener; + import android.os.storage.IMountService.Stub; import android.net.Uri; @@ -41,6 +43,9 @@ import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.storage.IMountService; +import android.os.storage.IMountShutdownObserver; +import android.os.storage.StorageEventListener; +import android.os.storage.StorageManager; import android.os.storage.StorageResultCode; import android.os.RemoteException; import android.os.ServiceManager; @@ -365,4 +370,256 @@ public class AsecTests extends AndroidTestCase { } } + /*------------ Tests for unmounting volume ---*/ + public final long MAX_WAIT_TIME=120*1000; + public final long WAIT_TIME_INCR=20*1000; + boolean getMediaState() { + try { + String mPath = Environment.getExternalStorageDirectory().toString(); + String state = getMs().getVolumeState(mPath); + return Environment.MEDIA_MOUNTED.equals(state); + } catch (RemoteException e) { + return false; + } + } + + boolean mountMedia() { + if (getMediaState()) { + return true; + } + try { + String mPath = Environment.getExternalStorageDirectory().toString(); + int ret = getMs().mountVolume(mPath); + return ret == StorageResultCode.OperationSucceeded; + } catch (RemoteException e) { + return false; + } + } + + class StorageListener extends StorageEventListener { + String oldState; + String newState; + String path; + private boolean doneFlag = false; + + public void action() { + synchronized (this) { + doneFlag = true; + notifyAll(); + } + } + + public boolean isDone() { + return doneFlag; + } + + @Override + public void onStorageStateChanged(String path, String oldState, String newState) { + if (localLOGV) Log.i(TAG, "Storage state changed from " + oldState + " to " + newState); + this.oldState = oldState; + this.newState = newState; + this.path = path; + action(); + } + } + + private boolean unmountMedia() { + if (!getMediaState()) { + return true; + } + String path = Environment.getExternalStorageDirectory().toString(); + StorageListener observer = new StorageListener(); + StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE); + sm.registerListener(observer); + try { + // Wait on observer + synchronized(observer) { + getMs().unmountVolume(path, false); + long waitTime = 0; + while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) { + observer.wait(WAIT_TIME_INCR); + waitTime += WAIT_TIME_INCR; + } + if(!observer.isDone()) { + throw new Exception("Timed out waiting for packageInstalled callback"); + } + return true; + } + } catch (Exception e) { + return false; + } finally { + sm.unregisterListener(observer); + } + } + public void testUnmount() { + boolean oldStatus = getMediaState(); + Log.i(TAG, "oldStatus="+oldStatus); + try { + // Mount media firsts + if (!getMediaState()) { + mountMedia(); + } + assertTrue(unmountMedia()); + } finally { + // Restore old status + boolean currStatus = getMediaState(); + if (oldStatus != currStatus) { + if (oldStatus) { + // Mount media + mountMedia(); + } else { + unmountMedia(); + } + } + } + } + + class MultipleStorageLis extends StorageListener { + int count = 0; + public void onStorageStateChanged(String path, String oldState, String newState) { + count++; + super.action(); + } + } + /* + * This test invokes unmount multiple time and expects the call back + * to be invoked just once. + */ + public void testUnmountMultiple() { + boolean oldStatus = getMediaState(); + StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE); + MultipleStorageLis observer = new MultipleStorageLis(); + try { + // Mount media firsts + if (!getMediaState()) { + mountMedia(); + } + String path = Environment.getExternalStorageDirectory().toString(); + sm.registerListener(observer); + // Wait on observer + synchronized(observer) { + for (int i = 0; i < 5; i++) { + getMs().unmountVolume(path, false); + } + long waitTime = 0; + while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) { + observer.wait(WAIT_TIME_INCR); + waitTime += WAIT_TIME_INCR; + } + if(!observer.isDone()) { + failStr("Timed out waiting for packageInstalled callback"); + } + } + assertEquals(observer.count, 1); + } catch (Exception e) { + failStr(e); + } finally { + sm.unregisterListener(observer); + // Restore old status + boolean currStatus = getMediaState(); + if (oldStatus != currStatus) { + if (oldStatus) { + // Mount media + mountMedia(); + } else { + unmountMedia(); + } + } + } + } + + class ShutdownObserver extends IMountShutdownObserver.Stub{ + private boolean doneFlag = false; + int statusCode; + + public void action() { + synchronized (this) { + doneFlag = true; + notifyAll(); + } + } + + public boolean isDone() { + return doneFlag; + } + public void onShutDownComplete(int statusCode) throws RemoteException { + this.statusCode = statusCode; + action(); + } + + } + + boolean invokeShutdown() { + IMountService ms = getMs(); + ShutdownObserver observer = new ShutdownObserver(); + synchronized (observer) { + try { + ms.shutdown(observer); + return true; + } catch (RemoteException e) { + failStr(e); + } + } + return false; + } + + public void testShutdown() { + boolean oldStatus = getMediaState(); + try { + // Mount media firsts + if (!getMediaState()) { + mountMedia(); + } + assertTrue(invokeShutdown()); + } finally { + // Restore old status + boolean currStatus = getMediaState(); + if (oldStatus != currStatus) { + if (oldStatus) { + // Mount media + mountMedia(); + } else { + unmountMedia(); + } + } + } + } + + /* + * This test invokes unmount multiple time and expects the call back + * to be invoked just once. + */ + public void testShutdownMultiple() { + boolean oldStatus = getMediaState(); + try { + // Mount media firsts + if (!getMediaState()) { + mountMedia(); + } + IMountService ms = getMs(); + ShutdownObserver observer = new ShutdownObserver(); + synchronized (observer) { + try { + ms.shutdown(observer); + for (int i = 0; i < 4; i++) { + ms.shutdown(null); + } + } catch (RemoteException e) { + failStr(e); + } + } + } finally { + // Restore old status + boolean currStatus = getMediaState(); + if (oldStatus != currStatus) { + if (oldStatus) { + // Mount media + mountMedia(); + } else { + unmountMedia(); + } + } + } + } + } diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java index 0b69020..d4435d3 100755 --- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java +++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java @@ -315,9 +315,9 @@ public class PackageManagerTests extends AndroidTestCase { if (!getInstallLoc(flags, expInstallLocation)) { assertEquals(srcPath, appInstallPath); assertEquals(publicSrcPath, appInstallPath); - assertFalse((info.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0); + assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); } else { - assertTrue((info.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0); + assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); assertTrue(srcPath.startsWith(SECURE_CONTAINERS_PREFIX)); assertTrue(publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX)); } @@ -1172,9 +1172,9 @@ public class PackageManagerTests extends AndroidTestCase { ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0); assertNotNull(info); if ((moveFlags & PackageManager.MOVE_INTERNAL) != 0) { - assertTrue((info.flags & ApplicationInfo.FLAG_ON_SDCARD) == 0); + assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0); } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0){ - assertTrue((info.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0); + assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); } } else { assertFalse(retCode); diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 537ae5e..735a80d 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -603,7 +603,7 @@ int doDump(Bundle* bundle) } else { printf("versionCode='' "); } - String8 versionName = getAttribute(tree, VERSION_NAME_ATTR, &error); + String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error); if (error != "") { fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string()); goto bail; diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index b7580b3..c0ebb59 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -379,14 +379,64 @@ enum { ATTR_LEADING_SPACES = -3, ATTR_TRAILING_SPACES = -4 }; -static int validateAttr(const String8& path, const ResXMLParser& parser, +static int validateAttr(const String8& path, const ResTable& table, + const ResXMLParser& parser, const char* ns, const char* attr, const char* validChars, bool required) { size_t len; ssize_t index = parser.indexOfAttribute(ns, attr); const uint16_t* str; - if (index >= 0 && (str=parser.getAttributeStringValue(index, &len)) != NULL) { + Res_value value; + if (index >= 0 && parser.getAttributeValue(index, &value) >= 0) { + const ResStringPool* pool = &parser.getStrings(); + if (value.dataType == Res_value::TYPE_REFERENCE) { + uint32_t specFlags = 0; + int strIdx; + if ((strIdx=table.resolveReference(&value, 0x10000000, NULL, &specFlags)) < 0) { + fprintf(stderr, "%s:%d: Tag <%s> attribute %s references unknown resid 0x%08x.\n", + path.string(), parser.getLineNumber(), + String8(parser.getElementName(&len)).string(), attr, + value.data); + return ATTR_NOT_FOUND; + } + + pool = table.getTableStringBlock(strIdx); + #if 0 + if (pool != NULL) { + str = pool->stringAt(value.data, &len); + } + printf("***** RES ATTR: %s specFlags=0x%x strIdx=%d: %s\n", attr, + specFlags, strIdx, str != NULL ? String8(str).string() : "???"); + #endif + if ((specFlags&~ResTable_typeSpec::SPEC_PUBLIC) != 0 && false) { + fprintf(stderr, "%s:%d: Tag <%s> attribute %s varies by configurations 0x%x.\n", + path.string(), parser.getLineNumber(), + String8(parser.getElementName(&len)).string(), attr, + specFlags); + return ATTR_NOT_FOUND; + } + } + if (value.dataType == Res_value::TYPE_STRING) { + if (pool == NULL) { + fprintf(stderr, "%s:%d: Tag <%s> attribute %s has no string block.\n", + path.string(), parser.getLineNumber(), + String8(parser.getElementName(&len)).string(), attr); + return ATTR_NOT_FOUND; + } + if ((str=pool->stringAt(value.data, &len)) == NULL) { + fprintf(stderr, "%s:%d: Tag <%s> attribute %s has corrupt string value.\n", + path.string(), parser.getLineNumber(), + String8(parser.getElementName(&len)).string(), attr); + return ATTR_NOT_FOUND; + } + } else { + fprintf(stderr, "%s:%d: Tag <%s> attribute %s has invalid type %d.\n", + path.string(), parser.getLineNumber(), + String8(parser.getElementName(&len)).string(), attr, + value.dataType); + return ATTR_NOT_FOUND; + } if (validChars) { for (size_t i=0; i<len; i++) { uint16_t c = str[i]; @@ -959,21 +1009,102 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) err = NO_ERROR; } + if (table.validateLocalizations()) { + hasErrors = true; + } + + if (hasErrors) { + return UNKNOWN_ERROR; + } + const sp<AaptFile> manifestFile(androidManifestFile->getFiles().valueAt(0)); String8 manifestPath(manifestFile->getPrintableSource()); + // Generate final compiled manifest file. + manifestFile->clearData(); + sp<XMLNode> manifestTree = XMLNode::parse(manifestFile); + if (manifestTree == NULL) { + return UNKNOWN_ERROR; + } + err = massageManifest(bundle, manifestTree); + if (err < NO_ERROR) { + return err; + } + err = compileXmlFile(assets, manifestTree, manifestFile, &table); + if (err < NO_ERROR) { + return err; + } + + //block.restart(); + //printXMLBlock(&block); + + // -------------------------------------------------------------- + // Generate the final resource table. + // Re-flatten because we may have added new resource IDs + // -------------------------------------------------------------- + + ResTable finalResTable; + sp<AaptFile> resFile; + + if (table.hasResources()) { + sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R")); + err = table.addSymbols(symbols); + if (err < NO_ERROR) { + return err; + } + + resFile = getResourceFile(assets); + if (resFile == NULL) { + fprintf(stderr, "Error: unable to generate entry for resource data\n"); + return UNKNOWN_ERROR; + } + + err = table.flatten(bundle, resFile); + if (err < NO_ERROR) { + return err; + } + + if (bundle->getPublicOutputFile()) { + FILE* fp = fopen(bundle->getPublicOutputFile(), "w+"); + if (fp == NULL) { + fprintf(stderr, "ERROR: Unable to open public definitions output file %s: %s\n", + (const char*)bundle->getPublicOutputFile(), strerror(errno)); + return UNKNOWN_ERROR; + } + if (bundle->getVerbose()) { + printf(" Writing public definitions to %s.\n", bundle->getPublicOutputFile()); + } + table.writePublicDefinitions(String16(assets->getPackage()), fp); + fclose(fp); + } + + // Read resources back in, + finalResTable.add(resFile->getData(), resFile->getSize(), NULL); + +#if 0 + NOISY( + printf("Generated resources:\n"); + finalResTable.print(); + ) +#endif + } + // Perform a basic validation of the manifest file. This time we // parse it with the comments intact, so that we can use them to // generate java docs... so we are not going to write this one // back out to the final manifest data. - err = compileXmlFile(assets, manifestFile, &table, + sp<AaptFile> outManifestFile = new AaptFile(manifestFile->getSourceFile(), + manifestFile->getGroupEntry(), + manifestFile->getResourceType()); + err = compileXmlFile(assets, manifestFile, + outManifestFile, &table, XML_COMPILE_ASSIGN_ATTRIBUTE_IDS | XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES); if (err < NO_ERROR) { return err; } ResXMLTree block; - block.setTo(manifestFile->getData(), manifestFile->getSize(), true); + block.setTo(outManifestFile->getData(), outManifestFile->getSize(), true); String16 manifest16("manifest"); String16 permission16("permission"); String16 permission_group16("permission-group"); @@ -1012,16 +1143,20 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) continue; } if (strcmp16(block.getElementName(&len), manifest16.string()) == 0) { - if (validateAttr(manifestPath, block, NULL, "package", + if (validateAttr(manifestPath, finalResTable, block, NULL, "package", packageIdentChars, true) != ATTR_OKAY) { hasErrors = true; } + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "sharedUserId", packageIdentChars, false) != ATTR_OKAY) { + hasErrors = true; + } } else if (strcmp16(block.getElementName(&len), permission16.string()) == 0 || strcmp16(block.getElementName(&len), permission_group16.string()) == 0) { const bool isGroup = strcmp16(block.getElementName(&len), permission_group16.string()) == 0; - if (validateAttr(manifestPath, block, RESOURCES_ANDROID_NAMESPACE, "name", - isGroup ? packageIdentCharsWithTheStupid + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "name", isGroup ? packageIdentCharsWithTheStupid : packageIdentChars, true) != ATTR_OKAY) { hasErrors = true; } @@ -1099,56 +1234,56 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) } syms->makeSymbolPublic(String8(e), srcPos); } else if (strcmp16(block.getElementName(&len), uses_permission16.string()) == 0) { - if (validateAttr(manifestPath, block, RESOURCES_ANDROID_NAMESPACE, "name", - packageIdentChars, true) != ATTR_OKAY) { + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "name", packageIdentChars, true) != ATTR_OKAY) { hasErrors = true; } } else if (strcmp16(block.getElementName(&len), instrumentation16.string()) == 0) { - if (validateAttr(manifestPath, block, RESOURCES_ANDROID_NAMESPACE, "name", - classIdentChars, true) != ATTR_OKAY) { + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "name", classIdentChars, true) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "targetPackage", packageIdentChars, true) != ATTR_OKAY) { hasErrors = true; } } else if (strcmp16(block.getElementName(&len), application16.string()) == 0) { - if (validateAttr(manifestPath, block, RESOURCES_ANDROID_NAMESPACE, "name", - classIdentChars, false) != ATTR_OKAY) { + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "name", classIdentChars, false) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "permission", packageIdentChars, false) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "process", processIdentChars, false) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "taskAffinity", processIdentChars, false) != ATTR_OKAY) { hasErrors = true; } } else if (strcmp16(block.getElementName(&len), provider16.string()) == 0) { - if (validateAttr(manifestPath, block, RESOURCES_ANDROID_NAMESPACE, "name", - classIdentChars, true) != ATTR_OKAY) { + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "name", classIdentChars, true) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "authorities", authoritiesIdentChars, true) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "permission", packageIdentChars, false) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "process", processIdentChars, false) != ATTR_OKAY) { hasErrors = true; @@ -1156,39 +1291,39 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) } else if (strcmp16(block.getElementName(&len), service16.string()) == 0 || strcmp16(block.getElementName(&len), receiver16.string()) == 0 || strcmp16(block.getElementName(&len), activity16.string()) == 0) { - if (validateAttr(manifestPath, block, RESOURCES_ANDROID_NAMESPACE, "name", - classIdentChars, true) != ATTR_OKAY) { + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "name", classIdentChars, true) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "permission", packageIdentChars, false) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "process", processIdentChars, false) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "taskAffinity", processIdentChars, false) != ATTR_OKAY) { hasErrors = true; } } else if (strcmp16(block.getElementName(&len), action16.string()) == 0 || strcmp16(block.getElementName(&len), category16.string()) == 0) { - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "name", packageIdentChars, true) != ATTR_OKAY) { hasErrors = true; } } else if (strcmp16(block.getElementName(&len), data16.string()) == 0) { - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "mimeType", typeIdentChars, true) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "scheme", schemeIdentChars, true) != ATTR_OKAY) { hasErrors = true; @@ -1197,76 +1332,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) } } - if (table.validateLocalizations()) { - hasErrors = true; - } - - if (hasErrors) { - return UNKNOWN_ERROR; - } - - // Generate final compiled manifest file. - manifestFile->clearData(); - sp<XMLNode> manifestTree = XMLNode::parse(manifestFile); - if (manifestTree == NULL) { - return UNKNOWN_ERROR; - } - err = massageManifest(bundle, manifestTree); - if (err < NO_ERROR) { - return err; - } - err = compileXmlFile(assets, manifestTree, manifestFile, &table); - if (err < NO_ERROR) { - return err; - } - - //block.restart(); - //printXMLBlock(&block); - - // -------------------------------------------------------------- - // Generate the final resource table. - // Re-flatten because we may have added new resource IDs - // -------------------------------------------------------------- - - if (table.hasResources()) { - sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R")); - err = table.addSymbols(symbols); - if (err < NO_ERROR) { - return err; - } - - sp<AaptFile> resFile(getResourceFile(assets)); - if (resFile == NULL) { - fprintf(stderr, "Error: unable to generate entry for resource data\n"); - return UNKNOWN_ERROR; - } - - err = table.flatten(bundle, resFile); - if (err < NO_ERROR) { - return err; - } - - if (bundle->getPublicOutputFile()) { - FILE* fp = fopen(bundle->getPublicOutputFile(), "w+"); - if (fp == NULL) { - fprintf(stderr, "ERROR: Unable to open public definitions output file %s: %s\n", - (const char*)bundle->getPublicOutputFile(), strerror(errno)); - return UNKNOWN_ERROR; - } - if (bundle->getVerbose()) { - printf(" Writing public definitions to %s.\n", bundle->getPublicOutputFile()); - } - table.writePublicDefinitions(String16(assets->getPackage()), fp); - fclose(fp); - } -#if 0 - NOISY( - ResTable rt; - rt.add(resFile->getData(), resFile->getSize(), NULL); - printf("Generated resources:\n"); - rt.print(); - ) -#endif + if (resFile != NULL) { // These resources are now considered to be a part of the included // resources, for others to reference. err = assets->addIncludedResources(resFile); @@ -1275,6 +1341,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) return err; } } + return err; } diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 1f9d152..ab5e937 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -28,6 +28,20 @@ status_t compileXmlFile(const sp<AaptAssets>& assets, } status_t compileXmlFile(const sp<AaptAssets>& assets, + const sp<AaptFile>& target, + const sp<AaptFile>& outTarget, + ResourceTable* table, + int options) +{ + sp<XMLNode> root = XMLNode::parse(target); + if (root == NULL) { + return UNKNOWN_ERROR; + } + + return compileXmlFile(assets, root, outTarget, table, options); +} + +status_t compileXmlFile(const sp<AaptAssets>& assets, const sp<XMLNode>& root, const sp<AaptFile>& target, ResourceTable* table, diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h index 60d0901..186c7ca 100644 --- a/tools/aapt/ResourceTable.h +++ b/tools/aapt/ResourceTable.h @@ -37,6 +37,12 @@ status_t compileXmlFile(const sp<AaptAssets>& assets, int options = XML_COMPILE_STANDARD_RESOURCE); status_t compileXmlFile(const sp<AaptAssets>& assets, + const sp<AaptFile>& target, + const sp<AaptFile>& outTarget, + ResourceTable* table, + int options = XML_COMPILE_STANDARD_RESOURCE); + +status_t compileXmlFile(const sp<AaptAssets>& assets, const sp<XMLNode>& xmlTree, const sp<AaptFile>& target, ResourceTable* table, diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java index 0928d2b..266d801 100644 --- a/wifi/java/android/net/wifi/WifiMonitor.java +++ b/wifi/java/android/net/wifi/WifiMonitor.java @@ -272,10 +272,8 @@ public class WifiMonitor { int connectTries = 0; while (true) { - synchronized (mWifiStateTracker) { - if (WifiNative.connectToSupplicant()) { - return true; - } + if (mWifiStateTracker.connectToSupplicant()) { + return true; } if (connectTries++ < 3) { nap(5); diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index c3c519f..f98cd28 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -26,6 +26,9 @@ import android.net.DhcpInfo; * <p/> * Note that methods whose names are not of the form "xxxCommand()" do * not talk to the supplicant daemon. + * Also, note that all WifiNative calls should happen in the + * WifiStateTracker class except for waitForEvent() call which is + * on a separate monitor channel for WifiMonitor * * {@hide} */ diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java index 810e4d2..cc47d08 100644 --- a/wifi/java/android/net/wifi/WifiStateTracker.java +++ b/wifi/java/android/net/wifi/WifiStateTracker.java @@ -544,9 +544,7 @@ public class WifiStateTracker extends NetworkStateTracker { */ void notifyScanResultsAvailable() { // reset the supplicant's handling of scan results to "normal" mode - synchronized (this) { - WifiNative.setScanResultHandlingCommand(SUPPL_SCAN_HANDLING_NORMAL); - } + setScanResultHandling(SUPPL_SCAN_HANDLING_NORMAL); sendEmptyMessage(EVENT_SCAN_RESULTS_AVAILABLE); } @@ -613,39 +611,6 @@ public class WifiStateTracker extends NetworkStateTracker { } /** - * Set the number of allowed radio frequency channels from the system - * setting value, if any. - * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g., - * the number of channels is invalid. - */ - public synchronized boolean setNumAllowedChannels() { - try { - return setNumAllowedChannels( - Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS)); - } catch (Settings.SettingNotFoundException e) { - if (mNumAllowedChannels != 0) { - WifiNative.setNumAllowedChannelsCommand(mNumAllowedChannels); - } - // otherwise, use the driver default - } - return true; - } - - /** - * Set the number of radio frequency channels that are allowed to be used - * in the current regulatory domain. - * @param numChannels the number of allowed channels. Must be greater than 0 - * and less than or equal to 16. - * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g., - * {@code numChannels} is outside the valid range. - */ - public synchronized boolean setNumAllowedChannels(int numChannels) { - mNumAllowedChannels = numChannels; - return WifiNative.setNumAllowedChannelsCommand(numChannels); - } - - /** * Set the run state to either "normal" or "scan-only". * @param scanOnlyMode true if the new mode should be scan-only. */ @@ -655,29 +620,19 @@ public class WifiStateTracker extends NetworkStateTracker { int scanType = (scanOnlyMode ? SUPPL_SCAN_HANDLING_LIST_ONLY : SUPPL_SCAN_HANDLING_NORMAL); if (LOCAL_LOGD) Log.v(TAG, "Scan-only mode changing to " + scanOnlyMode + " scanType=" + scanType); - if (WifiNative.setScanResultHandlingCommand(scanType)) { + if (setScanResultHandling(scanType)) { mIsScanOnly = scanOnlyMode; if (!isDriverStopped()) { if (scanOnlyMode) { - WifiNative.disconnectCommand(); + disconnect(); } else { - WifiNative.reconnectCommand(); + reconnectCommand(); } } } } } - /** - * Enable or disable Bluetooth coexistence scan mode. When this mode is on, - * some of the low-level scan parameters used by the driver are changed to - * reduce interference with A2DP streaming. - * - * @param isBluetoothPlaying whether to enable or disable this mode - */ - public synchronized void setBluetoothScanMode(boolean isBluetoothPlaying) { - WifiNative.setBluetoothCoexistenceScanModeCommand(isBluetoothPlaying); - } private void checkIsBluetoothPlaying() { boolean isBluetoothPlaying = false; @@ -765,10 +720,8 @@ public class WifiStateTracker extends NetworkStateTracker { * The MAC address isn't going to change, so just request it * once here. */ - String macaddr; - synchronized (this) { - macaddr = WifiNative.getMacAddressCommand(); - } + String macaddr = getMacAddress(); + if (macaddr != null) { mWifiInfo.setMacAddress(macaddr); } @@ -831,9 +784,8 @@ public class WifiStateTracker extends NetworkStateTracker { // [ 1- 0] Connected to supplicant (1), disconnected from supplicant (0) , // or supplicant died (2) EventLog.writeEvent(EVENTLOG_SUPPLICANT_CONNECTION_STATE_CHANGED, died ? 2 : 0); - synchronized (this) { - WifiNative.closeSupplicantConnection(); - } + closeSupplicantConnection(); + if (died) { resetConnections(true); } @@ -861,9 +813,7 @@ public class WifiStateTracker extends NetworkStateTracker { // Only do this if we haven't gotten a new supplicant status since the timer // started if (mNumSupplicantStateChanges == msg.arg1) { - synchronized (this) { - WifiNative.scanCommand(false); // do a passive scan - } + scan(false); // do a passive scan } break; @@ -954,13 +904,9 @@ public class WifiStateTracker extends NetworkStateTracker { if (mRunState == RUN_STATE_RUNNING && !mIsScanOnly && networkId != -1) { sendMessageDelayed(reconnectMsg, RECONNECT_DELAY_MSECS); } else if (mRunState == RUN_STATE_STOPPING) { - synchronized (this) { - WifiNative.stopDriverCommand(); - } + stopDriver(); } else if (mRunState == RUN_STATE_STARTING && !mIsScanOnly) { - synchronized (this) { - WifiNative.reconnectCommand(); - } + reconnectCommand(); } } else if (newState == SupplicantState.DISCONNECTED) { mHaveIpAddress = false; @@ -1129,9 +1075,7 @@ public class WifiStateTracker extends NetworkStateTracker { } addToBlacklist(BSSID); } - synchronized(this) { - WifiNative.reconnectCommand(); - } + reconnectCommand(); } break; @@ -1174,9 +1118,7 @@ public class WifiStateTracker extends NetworkStateTracker { mHaveIpAddress = false; mWifiInfo.setIpAddress(0); mObtainingIpAddress = false; - synchronized(this) { - WifiNative.disconnectCommand(); - } + disconnect(); } break; @@ -1199,11 +1141,11 @@ public class WifiStateTracker extends NetworkStateTracker { if (mRunState == RUN_STATE_STARTING) { mRunState = RUN_STATE_RUNNING; if (!mIsScanOnly) { - WifiNative.reconnectCommand(); + reconnectCommand(); } else { // In some situations, supplicant needs to be kickstarted to // start the background scanning - WifiNative.scanCommand(true); + scan(true); } } } @@ -1245,12 +1187,6 @@ public class WifiStateTracker extends NetworkStateTracker { return disabledNetwork; } - public synchronized void setScanMode(boolean isScanModeActive) { - if (mIsScanModeActive != isScanModeActive) { - WifiNative.setScanModeCommand(mIsScanModeActive = isScanModeActive); - } - } - private void configureInterface() { checkPollTimer(); mLastSignalLevel = -1; @@ -1371,10 +1307,7 @@ public class WifiStateTracker extends NetworkStateTracker { } private void requestConnectionStatus(WifiInfo info) { - String reply; - synchronized (this) { - reply = WifiNative.statusCommand(); - } + String reply = status(); if (reply == null) { return; } @@ -1423,7 +1356,7 @@ public class WifiStateTracker extends NetworkStateTracker { */ private synchronized void requestPolledInfo(WifiInfo info, boolean polling) { - int newRssi = (polling ? WifiNative.getRssiApproxCommand() : WifiNative.getRssiCommand()); + int newRssi = (polling ? getRssiApprox() : getRssi()); if (newRssi != -1 && -200 < newRssi && newRssi < 256) { // screen out invalid values /* some implementations avoid negative values by adding 256 * so we need to adjust for that here. @@ -1451,7 +1384,7 @@ public class WifiStateTracker extends NetworkStateTracker { } else { info.setRssi(-200); } - int newLinkSpeed = WifiNative.getLinkSpeedCommand(); + int newLinkSpeed = getLinkSpeed(); if (newLinkSpeed != -1) { info.setLinkSpeed(newLinkSpeed); } @@ -1521,9 +1454,9 @@ public class WifiStateTracker extends NetworkStateTracker { mRunState = RUN_STATE_STOPPING; if (mWifiInfo.getSupplicantState() == SupplicantState.DORMANT) { - return WifiNative.stopDriverCommand(); + return stopDriver(); } else { - return WifiNative.disconnectCommand(); + return disconnect(); } } else { /* @@ -1547,17 +1480,213 @@ public class WifiStateTracker extends NetworkStateTracker { if (mRunState == RUN_STATE_STOPPED) { mRunState = RUN_STATE_STARTING; resetConnections(true); - return WifiNative.startDriverCommand(); + return startDriver(); } else if (mRunState == RUN_STATE_STOPPING) { mRunState = RUN_STATE_STARTING; } return true; } + /** + * TODO: add documentation to all the native calls + * along with conditional checks to make sure + * native calls dont happen when wifi is not enabled + */ + + public synchronized boolean loadDriver() { + return WifiNative.loadDriver(); + } + + public synchronized boolean unloadDriver() { + return WifiNative.unloadDriver(); + } + + public synchronized boolean startSupplicant() { + return WifiNative.startSupplicant(); + } + + public synchronized boolean stopSupplicant() { + return WifiNative.stopSupplicant(); + } + + public synchronized boolean connectToSupplicant() { + return WifiNative.connectToSupplicant(); + } + + public synchronized void closeSupplicantConnection() { + WifiNative.closeSupplicantConnection(); + } + + public synchronized boolean ping() { + return WifiNative.pingCommand(); + } + + public synchronized boolean scan(boolean forceActive) { + return WifiNative.scanCommand(forceActive); + } + + public synchronized boolean setScanResultHandling(int mode) { + return WifiNative.setScanResultHandlingCommand(mode); + } + + public synchronized String scanResults() { + return WifiNative.scanResultsCommand(); + } + + public synchronized void setScanMode(boolean isScanModeActive) { + if (mIsScanModeActive != isScanModeActive) { + WifiNative.setScanModeCommand(mIsScanModeActive = isScanModeActive); + } + } + + public synchronized boolean disconnect() { + return WifiNative.disconnectCommand(); + } + + public synchronized boolean reconnectCommand() { + return WifiNative.reconnectCommand(); + } + + public synchronized int addNetwork() { + return WifiNative.addNetworkCommand(); + } + public synchronized boolean removeNetwork(int networkId) { return mDisconnectExpected = WifiNative.removeNetworkCommand(networkId); } + public synchronized boolean enableNetwork(int netId, boolean disableOthers) { + return WifiNative.enableNetworkCommand(netId, disableOthers); + } + + public synchronized boolean disableNetwork(int netId) { + return WifiNative.disableNetworkCommand(netId); + } + + public synchronized boolean reassociate() { + return WifiNative.reassociateCommand(); + } + + public synchronized boolean addToBlacklist(String bssid) { + return WifiNative.addToBlacklistCommand(bssid); + } + + public synchronized boolean clearBlacklist() { + return WifiNative.clearBlacklistCommand(); + } + + public synchronized String listNetworks() { + return WifiNative.listNetworksCommand(); + } + + public synchronized String getNetworkVariable(int netId, String name) { + return WifiNative.getNetworkVariableCommand(netId, name); + } + + public synchronized boolean setNetworkVariable(int netId, String name, String value) { + return WifiNative.setNetworkVariableCommand(netId, name, value); + } + + public synchronized String status() { + return WifiNative.statusCommand(); + } + + public synchronized int getRssi() { + return WifiNative.getRssiApproxCommand(); + } + + public synchronized int getRssiApprox() { + return WifiNative.getRssiApproxCommand(); + } + + public synchronized int getLinkSpeed() { + return WifiNative.getLinkSpeedCommand(); + } + + public synchronized String getMacAddress() { + return WifiNative.getMacAddressCommand(); + } + + public synchronized boolean startDriver() { + return WifiNative.startDriverCommand(); + } + + public synchronized boolean stopDriver() { + return WifiNative.stopDriverCommand(); + } + + public synchronized boolean startPacketFiltering() { + return WifiNative.startPacketFiltering(); + } + + public synchronized boolean stopPacketFiltering() { + return WifiNative.stopPacketFiltering(); + } + + public synchronized boolean setPowerMode(int mode) { + return WifiNative.setPowerModeCommand(mode); + } + + /** + * Set the number of allowed radio frequency channels from the system + * setting value, if any. + * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g., + * the number of channels is invalid. + */ + public synchronized boolean setNumAllowedChannels() { + try { + return setNumAllowedChannels( + Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS)); + } catch (Settings.SettingNotFoundException e) { + if (mNumAllowedChannels != 0) { + WifiNative.setNumAllowedChannelsCommand(mNumAllowedChannels); + } + // otherwise, use the driver default + } + return true; + } + + /** + * Set the number of radio frequency channels that are allowed to be used + * in the current regulatory domain. + * @param numChannels the number of allowed channels. Must be greater than 0 + * and less than or equal to 16. + * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g., + * {@code numChannels} is outside the valid range. + */ + public synchronized boolean setNumAllowedChannels(int numChannels) { + mNumAllowedChannels = numChannels; + return WifiNative.setNumAllowedChannelsCommand(numChannels); + } + + public synchronized int getNumAllowedChannels() { + return WifiNative.getNumAllowedChannelsCommand(); + } + + public synchronized boolean setBluetoothCoexistenceMode(int mode) { + return WifiNative.setBluetoothCoexistenceModeCommand(mode); + } + + /** + * Enable or disable Bluetooth coexistence scan mode. When this mode is on, + * some of the low-level scan parameters used by the driver are changed to + * reduce interference with A2DP streaming. + * + * @param isBluetoothPlaying whether to enable or disable this mode + */ + public synchronized void setBluetoothScanMode(boolean isBluetoothPlaying) { + WifiNative.setBluetoothCoexistenceScanModeCommand(isBluetoothPlaying); + } + + public synchronized boolean saveConfig() { + return WifiNative.saveConfigCommand(); + } + + public synchronized boolean reloadConfig() { + return WifiNative.reloadConfigCommand(); + } + public boolean setRadio(boolean turnOn) { return mWM.setWifiEnabled(turnOn); } @@ -1571,7 +1700,7 @@ public class WifiStateTracker extends NetworkStateTracker { public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) { return -1; } - + /** * {@inheritDoc} * There are currently no Wi-Fi-specific features supported. @@ -1706,18 +1835,6 @@ public class WifiStateTracker extends NetworkStateTracker { mNumScansSinceNetworkStateChange = 0; } - public synchronized boolean reassociate() { - return WifiNative.reassociateCommand(); - } - - public synchronized boolean addToBlacklist(String bssid) { - return WifiNative.addToBlacklistCommand(bssid); - } - - public synchronized boolean clearBlacklist() { - return WifiNative.clearBlacklistCommand(); - } - @Override public String toString() { StringBuffer sb = new StringBuffer(); @@ -1796,15 +1913,12 @@ public class WifiStateTracker extends NetworkStateTracker { modifiedBluetoothCoexistenceMode = true; // Disable the coexistence mode - synchronized (WifiStateTracker.this) { - WifiNative.setBluetoothCoexistenceModeCommand( - WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); - } - } - - synchronized (WifiStateTracker.this) { - WifiNative.setPowerModeCommand(DRIVER_POWER_MODE_ACTIVE); + setBluetoothCoexistenceMode( + WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); } + + setPowerMode(DRIVER_POWER_MODE_ACTIVE); + synchronized (this) { // A new request is being made, so assume we will callback mCancelCallback = false; @@ -1818,18 +1932,15 @@ public class WifiStateTracker extends NetworkStateTracker { Log.i(TAG, "DhcpHandler: DHCP request failed: " + NetworkUtils.getDhcpError()); } - synchronized (WifiStateTracker.this) { - WifiNative.setPowerModeCommand(DRIVER_POWER_MODE_AUTO); - } - + + setPowerMode(DRIVER_POWER_MODE_AUTO); + if (modifiedBluetoothCoexistenceMode) { // Set the coexistence mode back to its default value - synchronized (WifiStateTracker.this) { - WifiNative.setBluetoothCoexistenceModeCommand( - WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); - } + setBluetoothCoexistenceMode( + WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); } - + synchronized (this) { if (!mCancelCallback) { mTarget.sendEmptyMessage(event); @@ -1838,7 +1949,7 @@ public class WifiStateTracker extends NetworkStateTracker { break; } } - + public synchronized void setCancelCallback(boolean cancelCallback) { mCancelCallback = cancelCallback; } |