Merge "adding Android Beam sample"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index eb8471a..1c85279 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -114,6 +114,7 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/fonts/Lohit_Hindi.ttf)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/fonts/DroidSans*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/api/14.txt b/api/14.txt
index 9f2a6df..e26311f 100644
--- a/api/14.txt
+++ b/api/14.txt
@@ -16583,10 +16583,6 @@
field public static final java.lang.String PHOTO_FILE_ID = "data14";
}
- public static final class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns {
- field public static final java.lang.String CONTENT_DIRECTORY = "stream_items";
- }
-
protected static abstract interface ContactsContract.ContactsColumns {
field public static final java.lang.String DISPLAY_NAME = "display_name";
field public static final java.lang.String HAS_PHONE_NUMBER = "has_phone_number";
@@ -16844,10 +16840,6 @@
field public static final java.lang.String DATA_ID = "data_id";
}
- public static final class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
- field public static final java.lang.String CONTENT_DIRECTORY = "stream_items";
- }
-
protected static abstract interface ContactsContract.RawContactsColumns {
field public static final java.lang.String AGGREGATION_MODE = "aggregation_mode";
field public static final java.lang.String CONTACT_ID = "contact_id";
@@ -16911,56 +16903,6 @@
field public static final android.net.Uri PROFILE_CONTENT_URI;
}
- public static final class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
- field public static final java.lang.String PHOTO = "photo";
- }
-
- protected static abstract interface ContactsContract.StreamItemPhotosColumns {
- field public static final java.lang.String PHOTO_FILE_ID = "photo_file_id";
- field public static final java.lang.String PHOTO_URI = "photo_uri";
- field public static final java.lang.String SORT_INDEX = "sort_index";
- field public static final java.lang.String STREAM_ITEM_ID = "stream_item_id";
- field public static final java.lang.String SYNC1 = "stream_item_photo_sync1";
- field public static final java.lang.String SYNC2 = "stream_item_photo_sync2";
- field public static final java.lang.String SYNC3 = "stream_item_photo_sync3";
- field public static final java.lang.String SYNC4 = "stream_item_photo_sync4";
- }
-
- public static final class ContactsContract.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
- field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item";
- field public static final android.net.Uri CONTENT_LIMIT_URI;
- field public static final android.net.Uri CONTENT_PHOTO_URI;
- field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item";
- field public static final android.net.Uri CONTENT_URI;
- field public static final java.lang.String MAX_ITEMS = "max_items";
- }
-
- public static final class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
- field public static final java.lang.String CONTENT_DIRECTORY = "photo";
- field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo";
- field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo";
- }
-
- protected static abstract interface ContactsContract.StreamItemsColumns {
- field public static final java.lang.String ACCOUNT_NAME = "account_name";
- field public static final java.lang.String ACCOUNT_TYPE = "account_type";
- field public static final java.lang.String COMMENTS = "comments";
- field public static final java.lang.String CONTACT_ID = "contact_id";
- field public static final java.lang.String CONTACT_LOOKUP_KEY = "contact_lookup";
- field public static final java.lang.String DATA_SET = "data_set";
- field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id";
- field public static final java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id";
- field public static final java.lang.String RES_ICON = "icon";
- field public static final java.lang.String RES_LABEL = "label";
- field public static final java.lang.String RES_PACKAGE = "res_package";
- field public static final java.lang.String SYNC1 = "stream_item_sync1";
- field public static final java.lang.String SYNC2 = "stream_item_sync2";
- field public static final java.lang.String SYNC3 = "stream_item_sync3";
- field public static final java.lang.String SYNC4 = "stream_item_sync4";
- field public static final java.lang.String TEXT = "text";
- field public static final java.lang.String TIMESTAMP = "timestamp";
- }
-
protected static abstract interface ContactsContract.SyncColumns implements android.provider.ContactsContract.BaseSyncColumns {
field public static final java.lang.String ACCOUNT_NAME = "account_name";
field public static final java.lang.String ACCOUNT_TYPE = "account_type";
diff --git a/api/current.txt b/api/current.txt
index 9f2a6df..e26311f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16583,10 +16583,6 @@
field public static final java.lang.String PHOTO_FILE_ID = "data14";
}
- public static final class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns {
- field public static final java.lang.String CONTENT_DIRECTORY = "stream_items";
- }
-
protected static abstract interface ContactsContract.ContactsColumns {
field public static final java.lang.String DISPLAY_NAME = "display_name";
field public static final java.lang.String HAS_PHONE_NUMBER = "has_phone_number";
@@ -16844,10 +16840,6 @@
field public static final java.lang.String DATA_ID = "data_id";
}
- public static final class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
- field public static final java.lang.String CONTENT_DIRECTORY = "stream_items";
- }
-
protected static abstract interface ContactsContract.RawContactsColumns {
field public static final java.lang.String AGGREGATION_MODE = "aggregation_mode";
field public static final java.lang.String CONTACT_ID = "contact_id";
@@ -16911,56 +16903,6 @@
field public static final android.net.Uri PROFILE_CONTENT_URI;
}
- public static final class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
- field public static final java.lang.String PHOTO = "photo";
- }
-
- protected static abstract interface ContactsContract.StreamItemPhotosColumns {
- field public static final java.lang.String PHOTO_FILE_ID = "photo_file_id";
- field public static final java.lang.String PHOTO_URI = "photo_uri";
- field public static final java.lang.String SORT_INDEX = "sort_index";
- field public static final java.lang.String STREAM_ITEM_ID = "stream_item_id";
- field public static final java.lang.String SYNC1 = "stream_item_photo_sync1";
- field public static final java.lang.String SYNC2 = "stream_item_photo_sync2";
- field public static final java.lang.String SYNC3 = "stream_item_photo_sync3";
- field public static final java.lang.String SYNC4 = "stream_item_photo_sync4";
- }
-
- public static final class ContactsContract.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
- field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item";
- field public static final android.net.Uri CONTENT_LIMIT_URI;
- field public static final android.net.Uri CONTENT_PHOTO_URI;
- field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item";
- field public static final android.net.Uri CONTENT_URI;
- field public static final java.lang.String MAX_ITEMS = "max_items";
- }
-
- public static final class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
- field public static final java.lang.String CONTENT_DIRECTORY = "photo";
- field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo";
- field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo";
- }
-
- protected static abstract interface ContactsContract.StreamItemsColumns {
- field public static final java.lang.String ACCOUNT_NAME = "account_name";
- field public static final java.lang.String ACCOUNT_TYPE = "account_type";
- field public static final java.lang.String COMMENTS = "comments";
- field public static final java.lang.String CONTACT_ID = "contact_id";
- field public static final java.lang.String CONTACT_LOOKUP_KEY = "contact_lookup";
- field public static final java.lang.String DATA_SET = "data_set";
- field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id";
- field public static final java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id";
- field public static final java.lang.String RES_ICON = "icon";
- field public static final java.lang.String RES_LABEL = "label";
- field public static final java.lang.String RES_PACKAGE = "res_package";
- field public static final java.lang.String SYNC1 = "stream_item_sync1";
- field public static final java.lang.String SYNC2 = "stream_item_sync2";
- field public static final java.lang.String SYNC3 = "stream_item_sync3";
- field public static final java.lang.String SYNC4 = "stream_item_sync4";
- field public static final java.lang.String TEXT = "text";
- field public static final java.lang.String TIMESTAMP = "timestamp";
- }
-
protected static abstract interface ContactsContract.SyncColumns implements android.provider.ContactsContract.BaseSyncColumns {
field public static final java.lang.String ACCOUNT_NAME = "account_name";
field public static final java.lang.String ACCOUNT_TYPE = "account_type";
diff --git a/cmds/bu/src/com/android/commands/bu/Backup.java b/cmds/bu/src/com/android/commands/bu/Backup.java
index 4c4bf98..046ccca 100644
--- a/cmds/bu/src/com/android/commands/bu/Backup.java
+++ b/cmds/bu/src/com/android/commands/bu/Backup.java
@@ -66,6 +66,7 @@
boolean saveApks = false;
boolean saveShared = false;
boolean doEverything = false;
+ boolean allIncludesSystem = true;
String arg;
while ((arg = nextArg()) != null) {
@@ -78,6 +79,10 @@
saveShared = true;
} else if ("-noshared".equals(arg)) {
saveShared = false;
+ } else if ("-system".equals(arg)) {
+ allIncludesSystem = true;
+ } else if ("-nosystem".equals(arg)) {
+ allIncludesSystem = false;
} else if ("-all".equals(arg)) {
doEverything = true;
} else {
@@ -102,7 +107,7 @@
try {
ParcelFileDescriptor fd = ParcelFileDescriptor.adoptFd(socketFd);
String[] packArray = new String[packages.size()];
- mBackupManager.fullBackup(fd, saveApks, saveShared, doEverything,
+ mBackupManager.fullBackup(fd, saveApks, saveShared, doEverything, allIncludesSystem,
packages.toArray(packArray));
} catch (RemoteException e) {
Log.e(TAG, "Unable to invoke backup manager for backup");
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 51c6f3a..24d3a6b 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -43,15 +43,18 @@
* modify various characteristics of the action bar or remove it completely.</p>
* <p>From your activity, you can retrieve an instance of {@link ActionBar} by calling {@link
* android.app.Activity#getActionBar getActionBar()}.</p>
- * <p>For information about how to use the action bar, including how to add action items, navigation
- * modes and more, read the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action
- * Bar</a> developer guide.</p>
* <p>In some cases, the action bar may be overlayed by another bar that enables contextual actions,
* using an {@link android.view.ActionMode}. For example, when the user selects one or more items in
* your activity, you can enable an action mode that offers actions specific to the selected
* items, with a UI that temporarily replaces the action bar. Although the UI may occupy the
* same space, the {@link android.view.ActionMode} APIs are distinct and independent from those for
* {@link ActionBar}.
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about how to use the action bar, including how to add action items, navigation
+ * modes and more, read the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action
+ * Bar</a> developer guide.</p>
+ * </div>
*/
public abstract class ActionBar {
/**
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 034e3c7..8e8d37d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -111,18 +111,6 @@
* {@link android.R.styleable#AndroidManifestActivity <activity>}
* declaration in their package's <code>AndroidManifest.xml</code>.</p>
*
- * <p>The Activity class is an important part of an application's overall lifecycle,
- * and the way activities are launched and put together is a fundamental
- * part of the platform's application model. For a detailed perspective on the structure of an
- * Android application and how activities behave, please read the
- * <a href="{@docRoot}guide/topics/fundamentals.html">Application Fundamentals</a> and
- * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a>
- * documents.</p>
- *
- * <p>You can also find a detailed discussion about how to create activities in the
- * <a href="{@docRoot}guide/topics/fundamentals/activities.html">Activities</a>
- * document.</p>
- *
* <p>Topics covered here:
* <ol>
* <li><a href="#Fragments">Fragments</a>
@@ -133,7 +121,22 @@
* <li><a href="#Permissions">Permissions</a>
* <li><a href="#ProcessLifecycle">Process Lifecycle</a>
* </ol>
- *
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>The Activity class is an important part of an application's overall lifecycle,
+ * and the way activities are launched and put together is a fundamental
+ * part of the platform's application model. For a detailed perspective on the structure of an
+ * Android application and how activities behave, please read the
+ * <a href="{@docRoot}guide/topics/fundamentals.html">Application Fundamentals</a> and
+ * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a>
+ * developer guides.</p>
+ *
+ * <p>You can also find a detailed discussion about how to create activities in the
+ * <a href="{@docRoot}guide/topics/fundamentals/activities.html">Activities</a>
+ * developer guide.</p>
+ * </div>
+ *
* <a name="Fragments"></a>
* <h3>Fragments</h3>
*
@@ -3246,6 +3249,7 @@
try {
String resolvedType = null;
if (fillInIntent != null) {
+ fillInIntent.setAllowFds(false);
resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
}
int result = ActivityManagerNative.getDefault()
@@ -3370,6 +3374,7 @@
if (mParent == null) {
int result = IActivityManager.START_RETURN_INTENT_TO_CALLER;
try {
+ intent.setAllowFds(false);
result = ActivityManagerNative.getDefault()
.startActivity(mMainThread.getApplicationThread(),
intent, intent.resolveTypeIfNeeded(
@@ -3419,6 +3424,7 @@
public boolean startNextMatchingActivity(Intent intent) {
if (mParent == null) {
try {
+ intent.setAllowFds(false);
return ActivityManagerNative.getDefault()
.startNextMatchingActivity(mToken, intent);
} catch (RemoteException e) {
@@ -3692,6 +3698,9 @@
}
if (false) Log.v(TAG, "Finishing self: token=" + mToken);
try {
+ if (resultData != null) {
+ resultData.setAllowFds(false);
+ }
if (ActivityManagerNative.getDefault()
.finishActivity(mToken, resultCode, resultData)) {
mFinished = true;
@@ -3812,6 +3821,7 @@
int flags) {
String packageName = getPackageName();
try {
+ data.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName,
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0776e10..99aae37 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2674,6 +2674,7 @@
// Next have the activity save its current state and managed dialogs...
if (!r.activity.mFinished && saveState) {
state = new Bundle();
+ state.setAllowFds(false);
mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
r.state = state;
}
@@ -2775,6 +2776,7 @@
if (!r.activity.mFinished && saveState) {
if (r.state == null) {
state = new Bundle();
+ state.setAllowFds(false);
mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
r.state = state;
} else {
@@ -3306,6 +3308,7 @@
}
if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
r.state = new Bundle();
+ r.state.setAllowFds(false);
mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 2139704..2bf1fb7 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -874,6 +874,7 @@
try {
String resolvedType = null;
if (fillInIntent != null) {
+ fillInIntent.setAllowFds(false);
resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
}
int result = ActivityManagerNative.getDefault()
@@ -892,6 +893,7 @@
public void sendBroadcast(Intent intent) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, false, false);
@@ -903,6 +905,7 @@
public void sendBroadcast(Intent intent, String receiverPermission) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, receiverPermission, false, false);
@@ -915,6 +918,7 @@
String receiverPermission) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, receiverPermission, true, false);
@@ -946,6 +950,7 @@
}
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, receiverPermission,
@@ -958,6 +963,7 @@
public void sendStickyBroadcast(Intent intent) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, false, true);
@@ -989,6 +995,7 @@
}
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, null,
@@ -1005,6 +1012,7 @@
intent.setDataAndType(intent.getData(), resolvedType);
}
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().unbroadcastIntent(
mMainThread.getApplicationThread(), intent);
} catch (RemoteException e) {
@@ -1069,6 +1077,7 @@
@Override
public ComponentName startService(Intent service) {
try {
+ service.setAllowFds(false);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()));
@@ -1086,6 +1095,7 @@
@Override
public boolean stopService(Intent service) {
try {
+ service.setAllowFds(false);
int res = ActivityManagerNative.getDefault().stopService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()));
@@ -1116,6 +1126,7 @@
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
+ service.setAllowFds(false);
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
@@ -1148,6 +1159,9 @@
public boolean startInstrumentation(ComponentName className,
String profileFile, Bundle arguments) {
try {
+ if (arguments != null) {
+ arguments.setAllowFds(false);
+ }
return ActivityManagerNative.getDefault().startInstrumentation(
className, profileFile, 0, arguments, null);
} catch (RemoteException e) {
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 3a08e6d..d423d98 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -162,9 +162,6 @@
* constructor to instantiate it. If the empty constructor is not available,
* a runtime exception will occur in some cases during state restore.
*
- * <p>For more documentation, also see the <a
- * href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p>
- *
* <p>Topics covered here:
* <ol>
* <li><a href="#OlderPlatforms">Older Platforms</a>
@@ -173,6 +170,12 @@
* <li><a href="#BackStack">Back Stack</a>
* </ol>
*
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about using fragments, read the
+ * <a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p>
+ * </div>
+ *
* <a name="OlderPlatforms"></a>
* <h3>Older Platforms</h3>
*
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 7a6759f..3da4f29 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -45,6 +45,12 @@
/**
* Interface for interacting with {@link Fragment} objects inside of an
* {@link Activity}
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about using fragments, read the
+ * <a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p>
+ * </div>
*/
public abstract class FragmentManager {
/**
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index c1f3cd6..6e99899 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -2,6 +2,12 @@
/**
* API for performing a set of Fragment operations.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about using fragments, read the
+ * <a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p>
+ * </div>
*/
public abstract class FragmentTransaction {
/**
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index f3bc495..d7f5c55 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1375,6 +1375,7 @@
}
}
try {
+ intent.setAllowFds(false);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
@@ -1415,6 +1416,7 @@
try {
String[] resolvedTypes = new String[intents.length];
for (int i=0; i<intents.length; i++) {
+ intents[i].setAllowFds(false);
resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
}
int result = ActivityManagerNative.getDefault()
@@ -1471,6 +1473,7 @@
}
}
try {
+ intent.setAllowFds(false);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 57a2695..96767ae 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -41,6 +41,12 @@
* long as necessary (and will not block the application's main loop), but
* only one request will be processed at a time.
*
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For a detailed discussion about how to create services, read the
+ * <a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a> developer guide.</p>
+ * </div>
+ *
* @see android.os.AsyncTask
*/
public abstract class IntentService extends Service {
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 2549c84..522f477 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -661,6 +661,9 @@
"Finishing broadcast to unregistered receiver");
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
+ if (extras != null) {
+ extras.setAllowFds(false);
+ }
mgr.finishReceiver(this, resultCode, data, extras, false);
} catch (RemoteException e) {
Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index 46a008d..89e9ddd 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -47,6 +47,12 @@
*
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.java
* fragment_cursor}
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about using loaders, read the
+ * <a href="{@docRoot}guide/topics/fundamentals/loaders.html">Loaders</a> developer guide.</p>
+ * </div>
*/
public abstract class LoaderManager {
/**
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index b4827cb..b0637a7 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -192,6 +192,7 @@
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
+ intent.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_ACTIVITY, packageName,
@@ -249,6 +250,7 @@
String packageName = context.getPackageName();
String[] resolvedTypes = new String[intents.length];
for (int i=0; i<intents.length; i++) {
+ intents[i].setAllowFds(false);
resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
}
try {
@@ -287,6 +289,7 @@
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
+ intent.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_BROADCAST, packageName,
@@ -324,6 +327,7 @@
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
+ intent.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_SERVICE, packageName,
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index ebde6e0..35bd8c0 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -50,10 +50,6 @@
* Threads</a>. The {@link IntentService} class is available
* as a standard implementation of Service that has its own thread where it
* schedules its work to be done.</p>
- *
- * <p>You can find a detailed discussion about how to create services in the
- * <a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a>
- * document.</p>
*
* <p>Topics covered here:
* <ol>
@@ -64,7 +60,13 @@
* <li><a href="#LocalServiceSample">Local Service Sample</a>
* <li><a href="#RemoteMessengerServiceSample">Remote Messenger Service Sample</a>
* </ol>
- *
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For a detailed discussion about how to create services, read the
+ * <a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a> developer guide.</p>
+ * </div>
+ *
* <a name="WhatIsAService"></a>
* <h3>What is a Service?</h3>
*
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index c154296..acdd0b5 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -157,11 +157,15 @@
* @param allApps If <code>true</code>, the resulting tar stream will include all
* installed applications' data, not just those named in the <code>packageNames</code>
* parameter.
+ * @param allIncludesSystem If {@code true}, then {@code allApps} will be interpreted
+ * as including packages pre-installed as part of the system. If {@code false},
+ * then setting {@code allApps} to {@code true} will mean only that all 3rd-party
+ * applications will be included in the dataset.
* @param packageNames The package names of the apps whose data (and optionally .apk files)
* are to be backed up. The <code>allApps</code> parameter supersedes this.
*/
void fullBackup(in ParcelFileDescriptor fd, boolean includeApks, boolean includeShared,
- boolean allApps, in String[] packageNames);
+ boolean allApps, boolean allIncludesSystem, in String[] packageNames);
/**
* Restore device content from the data stream passed through the given socket. The
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index 028149b..d71a8d6 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -90,7 +90,14 @@
* <li><a href="#Permissions">Permissions</a>
* <li><a href="#ProcessLifecycle">Process Lifecycle</a>
* </ol>
- *
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about how to use this class to receive and resolve intents, read the
+ * <a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
+ * developer guide.</p>
+ * </div>
+ *
* <a name="ReceiverLifecycle"></a>
* <h3>Receiver Lifecycle</h3>
*
@@ -366,6 +373,9 @@
mFinished = true;
try {
+ if (mResultExtras != null) {
+ mResultExtras.setAllowFds(false);
+ }
if (mOrderedHint) {
am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
mAbortBroadcast);
@@ -462,6 +472,7 @@
IActivityManager am = ActivityManagerNative.getDefault();
IBinder binder = null;
try {
+ service.setAllowFds(false);
binder = am.peekService(service, service.resolveTypeIfNeeded(
myContext.getContentResolver()));
} catch (RemoteException e) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index f44d038..2be5153 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -55,13 +55,21 @@
* {@link android.content.Context#bindService} to communicate with a
* background {@link android.app.Service}.
*
- * <p>An Intent provides a facility for performing late runtime binding between
- * the code in different applications. Its most significant use is in the
- * launching of activities, where it can be thought of as the glue between
- * activities. It is
- * basically a passive data structure holding an abstract description of an
- * action to be performed. The primary pieces of information in an intent
- * are:</p>
+ * <p>An Intent provides a facility for performing late runtime binding between the code in
+ * different applications. Its most significant use is in the launching of activities, where it
+ * can be thought of as the glue between activities. It is basically a passive data structure
+ * holding an abstract description of an action to be performed.</p>
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about how to create and resolve intents, read the
+ * <a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
+ * developer guide.</p>
+ * </div>
+ *
+ * <a name="IntentStructure"></a>
+ * <h3>Intent Structure</h3>
+ * <p>The primary pieces of information in an intent are:</p>
*
* <ul>
* <li> <p><b>action</b> -- The general action to be performed, such as
@@ -3568,6 +3576,13 @@
return mExtras != null && mExtras.hasFileDescriptors();
}
+ /** @hide */
+ public void setAllowFds(boolean allowFds) {
+ if (mExtras != null) {
+ mExtras.setAllowFds(allowFds);
+ }
+ }
+
/**
* Retrieve extended data from the intent.
*
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index f9b3fd5..3b0d846 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -71,6 +71,14 @@
* To specify a path, you also must specify both one or more authorities and
* one or more schemes it is associated with.
*
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about how to create and resolve intents, read the
+ * <a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
+ * developer guide.</p>
+ * </div>
+ *
+ * <h3>Filter Rules</h3>
* <p>A match is based on the following rules. Note that
* for an IntentFilter to match an Intent, three conditions must hold:
* the <strong>action</strong> and <strong>category</strong> must match, and
diff --git a/core/java/android/content/Loader.java b/core/java/android/content/Loader.java
index 368c33e..b962800 100644
--- a/core/java/android/content/Loader.java
+++ b/core/java/android/content/Loader.java
@@ -40,8 +40,12 @@
*
* <p>Most implementations should not derive directly from this class, but
* instead inherit from {@link AsyncTaskLoader}.</p>
- * <p>For more information, see the <a
- * href="{@docRoot}guide/topics/fundamentals/loaders.html">Loaders</a> developer guide.</p>
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about using loaders, read the
+ * <a href="{@docRoot}guide/topics/fundamentals/loaders.html">Loaders</a> developer guide.</p>
+ * </div>
*
* @param <D> The result returned when the load is complete
*/
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 127efa2..4225393 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -1301,7 +1301,7 @@
elapsedTime = authoritySyncStats.elapsedTime;
times = authoritySyncStats.times;
- timeStr = String.format("%d/%d%%",
+ timeStr = String.format("%ds/%d%%",
elapsedTime / 1000,
elapsedTime * 100 / totalElapsedTime);
timesStr = String.format("%d/%d%%",
@@ -1309,32 +1309,30 @@
times * 100 / totalTimes);
pw.printf(authorityFormat, name, timesStr, timeStr);
- if (authoritySyncStats.accountMap.size() > 1) {
- final List<AccountSyncStats> sortedAccounts =
- new ArrayList<AccountSyncStats>(
- authoritySyncStats.accountMap.values());
- Collections.sort(sortedAccounts, new Comparator<AccountSyncStats>() {
- @Override
- public int compare(AccountSyncStats lhs, AccountSyncStats rhs) {
- // reverse order
- int compare = Integer.compare(rhs.times, lhs.times);
- if (compare == 0) {
- compare = Long.compare(rhs.elapsedTime, lhs.elapsedTime);
- }
- return compare;
+ final List<AccountSyncStats> sortedAccounts =
+ new ArrayList<AccountSyncStats>(
+ authoritySyncStats.accountMap.values());
+ Collections.sort(sortedAccounts, new Comparator<AccountSyncStats>() {
+ @Override
+ public int compare(AccountSyncStats lhs, AccountSyncStats rhs) {
+ // reverse order
+ int compare = Integer.compare(rhs.times, lhs.times);
+ if (compare == 0) {
+ compare = Long.compare(rhs.elapsedTime, lhs.elapsedTime);
}
- });
- for (AccountSyncStats stats: sortedAccounts) {
- elapsedTime = stats.elapsedTime;
- times = stats.times;
- timeStr = String.format("%d/%d%%",
- elapsedTime / 1000,
- elapsedTime * 100 / totalElapsedTime);
- timesStr = String.format("%d/%d%%",
- times,
- times * 100 / totalTimes);
- pw.printf(accountFormat, stats.name, timesStr, timeStr);
+ return compare;
}
+ });
+ for (AccountSyncStats stats: sortedAccounts) {
+ elapsedTime = stats.elapsedTime;
+ times = stats.times;
+ timeStr = String.format("%ds/%d%%",
+ elapsedTime / 1000,
+ elapsedTime * 100 / totalElapsedTime);
+ timesStr = String.format("%d/%d%%",
+ times,
+ times * 100 / totalTimes);
+ pw.printf(accountFormat, stats.name, timesStr, timeStr);
}
pw.println(separator);
}
@@ -1342,9 +1340,8 @@
pw.println();
pw.println("Recent Sync History");
final String format = " %-" + maxAccount + "s %s\n";
- String lastAuthorityName = null;
- String lastAccountKey = null;
- long lastEventTime = 0;
+ final Map<String, Long> lastTimeMap = Maps.newHashMap();
+
for (int i = 0; i < N; i++) {
SyncStorageEngine.SyncHistoryItem item = items.get(i);
SyncStorageEngine.AuthorityInfo authority
@@ -1363,21 +1360,32 @@
final long eventTime = item.eventTime;
time.set(eventTime);
- pw.printf(" #%-3d: %s %8s %5.1fs",
+ final String key = authorityName + "/" + accountKey;
+ final Long lastEventTime = lastTimeMap.get(key);
+ final String diffString;
+ if (lastEventTime == null) {
+ diffString = "";
+ } else {
+ final long diff = (lastEventTime - eventTime) / 1000;
+ if (diff < 60) {
+ diffString = String.valueOf(diff);
+ } else if (diff < 3600) {
+ diffString = String.format("%02d:%02d", diff / 60, diff % 60);
+ } else {
+ final long sec = diff % 3600;
+ diffString = String.format("%02d:%02d:%02d",
+ diff / 3600, sec / 60, sec % 60);
+ }
+ }
+ lastTimeMap.put(key, eventTime);
+
+ pw.printf(" #%-3d: %s %8s %5.1fs %8s",
i + 1,
formatTime(eventTime),
SyncStorageEngine.SOURCES[item.source],
- ((float) elapsedTime) / 1000);
- if (authorityName.equals(lastAuthorityName) && accountKey.equals(lastAccountKey)) {
- final long span = (lastEventTime - eventTime) / 1000;
- pw.printf(" %02d:%02d\n", span / 60, span % 60);
- } else {
- pw.printf(format, accountKey, authorityName);
- }
-
- lastAuthorityName = authorityName;
- lastAccountKey = accountKey;
- lastEventTime = eventTime;
+ ((float) elapsedTime) / 1000,
+ diffString);
+ pw.printf(format, accountKey, authorityName);
if (item.event != SyncStorageEngine.EVENT_STOP
|| item.upstreamActivity != 0
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index 79c9395..fc6a44a 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -336,17 +336,17 @@
DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
if (dhcpAction == DhcpAction.START) {
- Log.d(TAG, "DHCP request on " + mInterfaceName);
+ if (DBG) Log.d(TAG, "DHCP request on " + mInterfaceName);
success = NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal);
mDhcpInfo = dhcpInfoInternal;
} else if (dhcpAction == DhcpAction.RENEW) {
- Log.d(TAG, "DHCP renewal on " + mInterfaceName);
+ if (DBG) Log.d(TAG, "DHCP renewal on " + mInterfaceName);
success = NetworkUtils.runDhcpRenew(mInterfaceName, dhcpInfoInternal);
dhcpInfoInternal.updateFromDhcpRequest(mDhcpInfo);
}
if (success) {
- Log.d(TAG, "DHCP succeeded on " + mInterfaceName);
+ if (DBG) Log.d(TAG, "DHCP succeeded on " + mInterfaceName);
long leaseDuration = dhcpInfoInternal.leaseDuration; //int to long conversion
//Sanity check for renewal
@@ -366,7 +366,7 @@
mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpInfoInternal)
.sendToTarget();
} else {
- Log.d(TAG, "DHCP failed on " + mInterfaceName + ": " +
+ Log.e(TAG, "DHCP failed on " + mInterfaceName + ": " +
NetworkUtils.getDhcpError());
NetworkUtils.stopDhcp(mInterfaceName);
mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0)
diff --git a/core/java/android/net/DnsPinger.java b/core/java/android/net/DnsPinger.java
index 3291e6b..11acabe 100644
--- a/core/java/android/net/DnsPinger.java
+++ b/core/java/android/net/DnsPinger.java
@@ -22,7 +22,7 @@
import android.os.Message;
import android.os.SystemClock;
import android.provider.Settings;
-import android.util.Slog;
+import android.util.Log;
import com.android.internal.util.Protocol;
@@ -51,7 +51,7 @@
* @hide
*/
public final class DnsPinger extends Handler {
- private static final boolean V = true;
+ private static final boolean DBG = false;
private static final int RECEIVE_POLL_INTERVAL_MS = 200;
private static final int DNS_PORT = 53;
@@ -154,7 +154,7 @@
newActivePing.socket.setNetworkInterface(NetworkInterface.getByName(
getCurrentLinkProperties().getInterfaceName()));
} catch (Exception e) {
- Slog.w(TAG,"sendDnsPing::Error binding to socket", e);
+ loge("sendDnsPing::Error binding to socket " + e);
}
newActivePing.packetId = (short) sRandom.nextInt();
@@ -165,8 +165,8 @@
// Send the DNS query
DatagramPacket packet = new DatagramPacket(buf,
buf.length, dnsAddress, DNS_PORT);
- if (V) {
- Slog.v(TAG, "Sending a ping " + newActivePing.internalId +
+ if (DBG) {
+ log("Sending a ping " + newActivePing.internalId +
" to " + dnsAddress.getHostAddress()
+ " with packetId " + newActivePing.packetId + ".");
}
@@ -196,15 +196,15 @@
curPing.result =
(int) (SystemClock.elapsedRealtime() - curPing.start);
} else {
- if (V) {
- Slog.v(TAG, "response ID didn't match, ignoring packet");
+ if (DBG) {
+ log("response ID didn't match, ignoring packet");
}
}
} catch (SocketTimeoutException e) {
// A timeout here doesn't mean anything - squelsh this exception
} catch (Exception e) {
- if (V) {
- Slog.v(TAG, "DnsPinger.pingDns got socket exception: ", e);
+ if (DBG) {
+ log("DnsPinger.pingDns got socket exception: " + e);
}
curPing.result = SOCKET_EXCEPTION;
}
@@ -244,13 +244,13 @@
public List<InetAddress> getDnsList() {
LinkProperties curLinkProps = getCurrentLinkProperties();
if (curLinkProps == null) {
- Slog.e(TAG, "getCurLinkProperties:: LP for type" + mConnectionType + " is null!");
+ loge("getCurLinkProperties:: LP for type" + mConnectionType + " is null!");
return mDefaultDns;
}
Collection<InetAddress> dnses = curLinkProps.getDnses();
if (dnses == null || dnses.size() == 0) {
- Slog.v(TAG, "getDns::LinkProps has null dns - returning default");
+ loge("getDns::LinkProps has null dns - returning default");
return mDefaultDns;
}
@@ -277,8 +277,8 @@
}
private void sendResponse(int internalId, int externalId, int responseVal) {
- if(V) {
- Slog.d(TAG, "Responding to packet " + internalId +
+ if(DBG) {
+ log("Responding to packet " + internalId +
" externalId " + externalId +
" and val " + responseVal);
}
@@ -304,7 +304,7 @@
try {
return NetworkUtils.numericToInetAddress(dns);
} catch (IllegalArgumentException e) {
- Slog.w(TAG, "getDefaultDns::malformed default dns address");
+ loge("getDefaultDns::malformed default dns address");
return null;
}
}
@@ -323,4 +323,12 @@
0, 1, // QTYPE, set to 1 = A (host address)
0, 1 // QCLASS, set to 1 = IN (internet)
};
+
+ private void log(String s) {
+ Log.d(TAG, s);
+ }
+
+ private void loge(String s) {
+ Log.e(TAG, s);
+ }
}
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index f3be39c..e554975 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -272,6 +272,17 @@
}
/**
+ * Combine all values from another {@link NetworkStats} into this object.
+ */
+ public void combineAllValues(NetworkStats another) {
+ NetworkStats.Entry entry = null;
+ for (int i = 0; i < another.size; i++) {
+ entry = another.getValues(i, entry);
+ combineValues(entry);
+ }
+ }
+
+ /**
* Find first stats index that matches the requested parameters.
*/
public int findIndex(String iface, int uid, int set, int tag) {
@@ -456,6 +467,34 @@
return result;
}
+ /**
+ * Return total statistics grouped by {@link #iface}; doesn't mutate the
+ * original structure.
+ */
+ public NetworkStats groupedByIface() {
+ final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
+
+ final Entry entry = new Entry();
+ entry.uid = UID_ALL;
+ entry.set = SET_ALL;
+ entry.tag = TAG_NONE;
+ entry.operations = 0L;
+
+ for (int i = 0; i < size; i++) {
+ // skip specific tags, since already counted in TAG_NONE
+ if (tag[i] != TAG_NONE) continue;
+
+ entry.iface = iface[i];
+ entry.rxBytes = rxBytes[i];
+ entry.rxPackets = rxPackets[i];
+ entry.txBytes = txBytes[i];
+ entry.txPackets = txPackets[i];
+ stats.combineValues(entry);
+ }
+
+ return stats;
+ }
+
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix);
pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 64bba54..9dea4c4 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -42,6 +42,13 @@
* and 4 steps, called <code>onPreExecute</code>, <code>doInBackground</code>,
* <code>onProgressUpdate</code> and <code>onPostExecute</code>.</p>
*
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about using tasks and threads, read the
+ * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and
+ * Threads</a> developer guide.</p>
+ * </div>
+ *
* <h2>Usage</h2>
* <p>AsyncTask must be subclassed to be used. The subclass will override at least
* one method ({@link #doInBackground}), and most often will override a
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index c288f8a..28206b7 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -54,6 +54,7 @@
private boolean mHasFds = false;
private boolean mFdsKnown = true;
+ private boolean mAllowFds = true;
/**
* The ClassLoader used when unparcelling data from mParcelledData.
@@ -186,7 +187,14 @@
public ClassLoader getClassLoader() {
return mClassLoader;
}
-
+
+ /** @hide */
+ public boolean setAllowFds(boolean allowFds) {
+ boolean orig = mAllowFds;
+ mAllowFds = allowFds;
+ return orig;
+ }
+
/**
* Clones the current Bundle. The internal map is cloned, but the keys and
* values to which it refers are copied by reference.
@@ -1589,24 +1597,29 @@
* @param parcel The parcel to copy this bundle to.
*/
public void writeToParcel(Parcel parcel, int flags) {
- if (mParcelledData != null) {
- int length = mParcelledData.dataSize();
- parcel.writeInt(length);
- parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
- parcel.appendFrom(mParcelledData, 0, length);
- } else {
- parcel.writeInt(-1); // dummy, will hold length
- parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
-
- int oldPos = parcel.dataPosition();
- parcel.writeMapInternal(mMap);
- int newPos = parcel.dataPosition();
-
- // Backpatch length
- parcel.setDataPosition(oldPos - 8);
- int length = newPos - oldPos;
- parcel.writeInt(length);
- parcel.setDataPosition(newPos);
+ final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds);
+ try {
+ if (mParcelledData != null) {
+ int length = mParcelledData.dataSize();
+ parcel.writeInt(length);
+ parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
+ parcel.appendFrom(mParcelledData, 0, length);
+ } else {
+ parcel.writeInt(-1); // dummy, will hold length
+ parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
+
+ int oldPos = parcel.dataPosition();
+ parcel.writeMapInternal(mMap);
+ int newPos = parcel.dataPosition();
+
+ // Backpatch length
+ parcel.setDataPosition(oldPos - 8);
+ int length = newPos - oldPos;
+ parcel.writeInt(length);
+ parcel.setDataPosition(newPos);
+ }
+ } finally {
+ parcel.restoreAllowFds(oldAllowFds);
}
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index e9ed676..15e3af4 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -323,6 +323,12 @@
*/
public final native void setDataCapacity(int size);
+ /** @hide */
+ public final native boolean pushAllowFds(boolean allowFds);
+
+ /** @hide */
+ public final native void restoreAllowFds(boolean lastValue);
+
/**
* Returns the raw bytes of the parcel.
*
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 886edaf..6d14dfc 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -238,6 +238,14 @@
public static final String CACHED_PHOTO_ID = "photo_id";
/**
+ * The cached formatted phone number.
+ * This value is not guaranteed to be present.
+ * <P>Type: TEXT</P>
+ * @hide
+ */
+ public static final String CACHED_FORMATTED_NUMBER = "formatted_number";
+
+ /**
* Adds a call to the call log.
*
* @param ci the CallerInfo object to get the target contact from. Can be null
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index fb119b3..8483b4f 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1611,9 +1611,16 @@
}
/**
+ * <p>
* A sub-directory of a single contact that contains all of the constituent raw contact
* {@link ContactsContract.StreamItems} rows. This directory can be used either
* with a {@link #CONTENT_URI} or {@link #CONTENT_LOOKUP_URI}.
+ * </p>
+ * <p>
+ * Querying for social stream data requires android.permission.READ_SOCIAL_STREAM
+ * permission.
+ * </p>
+ * @hide
*/
public static final class StreamItems implements StreamItemsColumns {
/**
@@ -2669,6 +2676,14 @@
* {@link ContactsContract.StreamItems} for a stand-alone table containing the
* same data.
* </p>
+ * <p>
+ * Access to the social stream through this sub-directory requires additional permissions
+ * beyond the read/write contact permissions required by the provider. Querying for
+ * social stream data requires android.permission.READ_SOCIAL_STREAM permission, and
+ * inserting or updating social stream items requires android.permission.WRITE_SOCIAL_STREAM
+ * permission.
+ * </p>
+ * @hide
*/
public static final class StreamItems implements BaseColumns, StreamItemsColumns {
/**
@@ -2963,6 +2978,12 @@
* transaction correspondingly. Insertion of more items beyond the limit will
* automatically lead to deletion of the oldest items, by {@link StreamItems#TIMESTAMP}.
* </p>
+ * <p>
+ * Access to the social stream through these URIs requires additional permissions beyond the
+ * read/write contact permissions required by the provider. Querying for social stream data
+ * requires android.permission.READ_SOCIAL_STREAM permission, and inserting or updating social
+ * stream items requires android.permission.WRITE_SOCIAL_STREAM permission.
+ * </p>
* <h3>Operations</h3>
* <dl>
* <dt><b>Insert</b></dt>
@@ -3075,6 +3096,7 @@
* </pre>
* </dd>
* </dl>
+ * @hide
*/
public static final class StreamItems implements BaseColumns, StreamItemsColumns {
/**
@@ -3135,6 +3157,12 @@
* directory append {@link StreamItems.StreamItemPhotos#CONTENT_DIRECTORY} to
* an individual stream item URI.
* </p>
+ * <p>
+ * Access to social stream photos requires additional permissions beyond the read/write
+ * contact permissions required by the provider. Querying for social stream photos
+ * requires android.permission.READ_SOCIAL_STREAM permission, and inserting or updating
+ * social stream photos requires android.permission.WRITE_SOCIAL_STREAM permission.
+ * </p>
*/
public static final class StreamItemPhotos
implements BaseColumns, StreamItemPhotosColumns {
@@ -3166,6 +3194,7 @@
* Columns in the StreamItems table.
*
* @see ContactsContract.StreamItems
+ * @hide
*/
protected interface StreamItemsColumns {
/**
@@ -3312,6 +3341,12 @@
* Constants for the stream_item_photos table, which contains photos associated with
* social stream updates.
* </p>
+ * <p>
+ * Access to social stream photos requires additional permissions beyond the read/write
+ * contact permissions required by the provider. Querying for social stream photos
+ * requires android.permission.READ_SOCIAL_STREAM permission, and inserting or updating
+ * social stream photos requires android.permission.WRITE_SOCIAL_STREAM permission.
+ * </p>
* <h3>Operations</h3>
* <dl>
* <dt><b>Insert</b></dt>
@@ -3450,6 +3485,7 @@
* <pre>
* </dd>
* </dl>
+ * @hide
*/
public static final class StreamItemPhotos implements BaseColumns, StreamItemPhotosColumns {
/**
@@ -3477,6 +3513,7 @@
* Columns in the StreamItemPhotos table.
*
* @see ContactsContract.StreamItemPhotos
+ * @hide
*/
protected interface StreamItemPhotosColumns {
/**
diff --git a/core/java/android/server/BluetoothAdapterStateMachine.java b/core/java/android/server/BluetoothAdapterStateMachine.java
index d26364e..da7c489 100644
--- a/core/java/android/server/BluetoothAdapterStateMachine.java
+++ b/core/java/android/server/BluetoothAdapterStateMachine.java
@@ -77,6 +77,12 @@
static final int PER_PROCESS_TURN_ON = 3;
static final int PER_PROCESS_TURN_OFF = 4;
+ // Turn on Bluetooth Module, Load firmware, and do all the preparation
+ // needed to get the Bluetooth Module ready but keep it not discoverable
+ // and not connectable. This way the Bluetooth Module can be quickly
+ // switched on if needed
+ static final int TURN_HOT = 5;
+
// Message(what) to report a event that the state machine need to respond to
//
// Event indicates sevice records have been loaded
@@ -94,23 +100,18 @@
// private internal messages
//
- // Turn on Bluetooth Module, Load firmware, and do all the preparation
- // needed to get the Bluetooth Module ready but keep it not discoverable
- // and not connectable. This way the Bluetooth Module can be quickly
- // switched on if needed
- private static final int TURN_HOT = 101;
// USER_TURN_ON is changed to TURN_ON_CONTINUE after we broadcast the
// state change intent so that we will not broadcast the intent again in
// other state
- private static final int TURN_ON_CONTINUE = 102;
+ private static final int TURN_ON_CONTINUE = 101;
// Unload firmware, turning off Bluetooth module power
- private static final int TURN_COLD = 103;
+ private static final int TURN_COLD = 102;
// Device disconnecting timeout happens
- private static final int DEVICES_DISCONNECT_TIMEOUT = 104;
+ private static final int DEVICES_DISCONNECT_TIMEOUT = 103;
// Prepare Bluetooth timeout happens
- private static final int PREPARE_BLUETOOTH_TIMEOUT = 105;
+ private static final int PREPARE_BLUETOOTH_TIMEOUT = 104;
// Bluetooth Powerdown timeout happens
- private static final int POWER_DOWN_TIMEOUT = 106;
+ private static final int POWER_DOWN_TIMEOUT = 105;
private Context mContext;
private BluetoothService mBluetoothService;
@@ -156,11 +157,6 @@
setInitialState(mPowerOff);
mPublicState = BluetoothAdapter.STATE_OFF;
-
- if (mContext.getResources().getBoolean
- (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
- sendMessage(TURN_HOT);
- }
}
/**
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 63da926..9ca5847 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -313,6 +313,10 @@
mAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothState = new BluetoothAdapterStateMachine(mContext, this, mAdapter);
mBluetoothState.start();
+ if (mContext.getResources().getBoolean
+ (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.TURN_HOT);
+ }
mEventLoop = mBluetoothState.getBluetoothEventLoop();
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d193d6e..8e5aefd 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -94,20 +94,10 @@
* their layout properties.
* </p>
*
- * <div class="special">
- * <p>For an introduction to using this class to develop your
- * application's user interface, read the Developer Guide documentation on
- * <strong><a href="{@docRoot}guide/topics/ui/index.html">User Interface</a></strong>. Special topics
- * include:
- * <br/><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a>
- * <br/><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a>
- * <br/><a href="{@docRoot}guide/topics/ui/layout-objects.html">Common Layout Objects</a>
- * <br/><a href="{@docRoot}guide/topics/ui/binding.html">Binding to Data with AdapterView</a>
- * <br/><a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a>
- * <br/><a href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a>
- * <br/><a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>
- * <br/><a href="{@docRoot}guide/topics/ui/how-android-draws.html">How Android Draws Views</a>.
- * </p>
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about using this class to develop your application's user interface,
+ * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
* </div>
*
* <a name="Using"></a>
@@ -1487,6 +1477,18 @@
}
/**
+ * Accessibility event types that are dispatched for text population.
+ */
+ private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
+ AccessibilityEvent.TYPE_VIEW_CLICKED
+ | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
+ | AccessibilityEvent.TYPE_VIEW_SELECTED
+ | AccessibilityEvent.TYPE_VIEW_FOCUSED
+ | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
+ | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
+ | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT;
+
+ /**
* Temporary Rect currently for use in setBackground(). This will probably
* be extended in the future to hold our own class with more than just
* a Rect. :)
@@ -3855,7 +3857,10 @@
return;
}
onInitializeAccessibilityEvent(event);
- dispatchPopulateAccessibilityEvent(event);
+ // Only a subset of accessibility events populates text content.
+ if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
+ dispatchPopulateAccessibilityEvent(event);
+ }
// In the beginning we called #isShown(), so we know that getParent() is not null.
getParent().requestSendAccessibilityEvent(this, event);
}
@@ -3876,6 +3881,10 @@
* {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
* is responsible for handling this call.
* </p>
+ * <p>
+ * <em>Note:</em> Accessibility events of certain types are not dispatched for
+ * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
+ * </p>
*
* @param event The event.
*
@@ -3895,12 +3904,6 @@
* Note: Called from the default {@link AccessibilityDelegate}.
*/
boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
- // Do not populate text to scroll events. They describe position change
- // and usually come from container with a lot of text which is not very
- // informative for accessibility purposes. Also they are fired frequently.
- if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
- return true;
- }
onPopulateAccessibilityEvent(event);
return false;
}
@@ -12093,6 +12096,39 @@
}
/**
+ * Finds a view by its unuque and stable accessibility id.
+ *
+ * @param accessibilityId The searched accessibility id.
+ * @return The found view.
+ */
+ final View findViewByAccessibilityId(int accessibilityId) {
+ if (accessibilityId < 0) {
+ return null;
+ }
+ return findViewByAccessibilityIdTraversal(accessibilityId);
+ }
+
+ /**
+ * Performs the traversal to find a view by its unuque and stable accessibility id.
+ *
+ * <strong>Note:</strong>This method does not stop at the root namespace
+ * boundary since the user can touch the screen at an arbitrary location
+ * potentially crossing the root namespace bounday which will send an
+ * accessibility event to accessibility services and they should be able
+ * to obtain the event source. Also accessibility ids are guaranteed to be
+ * unique in the window.
+ *
+ * @param accessibilityId The accessibility id.
+ * @return The found view.
+ */
+ View findViewByAccessibilityIdTraversal(int accessibilityId) {
+ if (getAccessibilityViewId() == accessibilityId) {
+ return this;
+ }
+ return null;
+ }
+
+ /**
* Look for a child view with the given tag. If this view has the given
* tag, return this view.
*
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index fb0d80a..5b4a6f8 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -821,6 +821,24 @@
}
}
+ @Override
+ View findViewByAccessibilityIdTraversal(int accessibilityId) {
+ View foundView = super.findViewByAccessibilityIdTraversal(accessibilityId);
+ if (foundView != null) {
+ return foundView;
+ }
+ final int childrenCount = mChildrenCount;
+ final View[] children = mChildren;
+ for (int i = 0; i < childrenCount; i++) {
+ View child = children[i];
+ foundView = child.findViewByAccessibilityIdTraversal(accessibilityId);
+ if (foundView != null) {
+ return foundView;
+ }
+ }
+ return null;
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9cb4e5e..e7c91f9 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -74,7 +74,6 @@
import android.widget.Scroller;
import com.android.internal.policy.PolicyManager;
-import com.android.internal.util.Predicate;
import com.android.internal.view.BaseSurfaceHolder;
import com.android.internal.view.IInputMethodCallback;
import com.android.internal.view.IInputMethodSession;
@@ -4462,9 +4461,6 @@
final class AccessibilityInteractionController {
private static final int POOL_SIZE = 5;
- private FindByAccessibilitytIdPredicate mFindByAccessibilityIdPredicate =
- new FindByAccessibilitytIdPredicate();
-
private ArrayList<AccessibilityNodeInfo> mTempAccessibilityNodeInfoList =
new ArrayList<AccessibilityNodeInfo>();
@@ -4551,11 +4547,8 @@
AccessibilityNodeInfo info = null;
try {
- FindByAccessibilitytIdPredicate predicate = mFindByAccessibilityIdPredicate;
- predicate.init(accessibilityId);
- View root = ViewRootImpl.this.mView;
- View target = root.findViewByPredicate(predicate);
- if (target != null && target.getVisibility() == View.VISIBLE) {
+ View target = findViewByAccessibilityId(accessibilityId);
+ if (target != null) {
info = target.createAccessibilityNodeInfo();
}
} finally {
@@ -4794,25 +4787,12 @@
if (root == null) {
return null;
}
- mFindByAccessibilityIdPredicate.init(accessibilityId);
- View foundView = root.findViewByPredicate(mFindByAccessibilityIdPredicate);
- if (foundView == null || foundView.getVisibility() != View.VISIBLE) {
+ View foundView = root.findViewByAccessibilityId(accessibilityId);
+ if (foundView != null && foundView.getVisibility() != View.VISIBLE) {
return null;
}
return foundView;
}
-
- private final class FindByAccessibilitytIdPredicate implements Predicate<View> {
- public int mSearchedId;
-
- public void init(int searchedId) {
- mSearchedId = searchedId;
- }
-
- public boolean apply(View view) {
- return (view.getAccessibilityViewId() == mSearchedId);
- }
- }
}
private class SendWindowContentChangedAccessibilityEvent implements Runnable {
@@ -4820,18 +4800,7 @@
public void run() {
if (mView != null) {
- // Check again for accessibility state since this is executed delayed.
- AccessibilityManager accessibilityManager =
- AccessibilityManager.getInstance(mView.mContext);
- if (accessibilityManager.isEnabled()) {
- // Send the event directly since we do not want to append the
- // source text because this is the text for the entire window
- // and we just want to notify that the content has changed.
- AccessibilityEvent event = AccessibilityEvent.obtain(
- AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
- mView.onInitializeAccessibilityEvent(event);
- accessibilityManager.sendAccessibilityEvent(event);
- }
+ mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
mIsPending = false;
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index c93b564..91fbb0e 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -69,14 +69,16 @@
* <em>Type:</em>{@link #TYPE_VIEW_CLICKED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <li>{@link #getSource()} - The source info (for registered clients).</li>
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
* <li>{@link #getEventTime()} - The event time.</li>
- * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #getText()} - The text of the source's sub-tree.</li>
* <li>{@link #isEnabled()} - Whether the source is enabled.</li>
* <li>{@link #isPassword()} - Whether the source is password.</li>
* <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
* </p>
* <p>
@@ -85,14 +87,16 @@
* <em>Type:</em>{@link #TYPE_VIEW_LONG_CLICKED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <li>{@link #getSource()} - The source info (for registered clients).</li>
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
* <li>{@link #getEventTime()} - The event time.</li>
- * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #getText()} - The text of the source's sub-tree.</li>
* <li>{@link #isEnabled()} - Whether the source is enabled.</li>
* <li>{@link #isPassword()} - Whether the source is password.</li>
* <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
* </p>
* <p>
@@ -101,16 +105,18 @@
* <em>Type:</em> {@link #TYPE_VIEW_SELECTED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <li>{@link #getSource()} - The source info (for registered clients).</li>
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
* <li>{@link #getEventTime()} - The event time.</li>
- * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #getText()} - The text of the source's sub-tree.</li>
* <li>{@link #isEnabled()} - Whether the source is enabled.</li>
* <li>{@link #isPassword()} - Whether the source is password.</li>
* <li>{@link #isChecked()} - Whether the source is checked.</li>
* <li>{@link #getItemCount()} - The number of selectable items of the source.</li>
* <li>{@link #getCurrentItemIndex()} - The currently selected item index.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
* </p>
* <p>
@@ -119,16 +125,18 @@
* <em>Type:</em> {@link #TYPE_VIEW_FOCUSED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <li>{@link #getSource()} - The source info (for registered clients).</li>
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
* <li>{@link #getEventTime()} - The event time.</li>
- * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #getText()} - The text of the source's sub-tree.</li>
* <li>{@link #isEnabled()} - Whether the source is enabled.</li>
* <li>{@link #isPassword()} - Whether the source is password.</li>
* <li>{@link #isChecked()} - Whether the source is checked.</li>
* <li>{@link #getItemCount()} - The number of focusable items on the screen.</li>
* <li>{@link #getCurrentItemIndex()} - The currently focused item index.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
* </p>
* <p>
@@ -137,6 +145,7 @@
* <em>Type:</em> {@link #TYPE_VIEW_TEXT_CHANGED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <li>{@link #getSource()} - The source info (for registered clients).</li>
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
@@ -149,7 +158,17 @@
* <li>{@link #getAddedCount()} - The number of added characters.</li>
* <li>{@link #getRemovedCount()} - The number of removed characters.</li>
* <li>{@link #getBeforeText()} - The text of the source before the change.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
* </p>
* <p>
* <b>View text selection changed</b> - represents the event of changing the text
@@ -157,35 +176,47 @@
* <em>Type:</em> {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} </br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <li>{@link #getSource()} - The source info (for registered clients).</li>
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
* <li>{@link #getEventTime()} - The event time.</li>
* <li>{@link #getText()} - The text of the source.</li>
- * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
* <li>{@link #isPassword()} - Whether the source is password.</li>
* <li>{@link #getFromIndex()} - The selection start index.</li>
* <li>{@link #getToIndex()} - The selection end index.</li>
* <li>{@link #getItemCount()} - The length of the source text.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
* </p>
* <p>
* <b>View scrolled</b> - represents the event of scrolling a view. If
* the source is a descendant of {@link android.widget.AdapterView} the
* scroll is reported in terms of visible items - the first visible item,
* the last visible item, and the total items - because the the source
- * is unaware if its pixel size since its adapter is responsible for
+ * is unaware of its pixel size since its adapter is responsible for
* creating views. In all other cases the scroll is reported as the current
* scroll on the X and Y axis respectively plus the height of the source in
* pixels.</br>
* <em>Type:</em> {@link #TYPE_VIEW_SCROLLED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <li>{@link #getSource()} - The source info (for registered clients).</li>
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
* <li>{@link #getEventTime()} - The event time.</li>
- * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #getText()} - The text of the source's sub-tree.</li>
* <li>{@link #isEnabled()} - Whether the source is enabled.</li>
* <li>{@link #getScrollX()} - The horizontal offset of the source
* (without descendants of AdapterView)).</li>
@@ -197,56 +228,165 @@
* (for descendants of AdapterView).</li>
* <li>{@link #getItemCount()} - The total items of the source (for descendants of AdapterView)
* or the height of the source in pixels (all other cases).</li>
+ * <li>{@link #getText()} - Text for providing more context.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
* </p>
* <p>
* <b>TRANSITION TYPES</b></br>
* </p>
+ * <p>
* <b>Window state changed</b> - represents the event of opening a
* {@link android.widget.PopupWindow}, {@link android.view.Menu},
* {@link android.app.Dialog}, etc.</br>
* <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <li>{@link #getSource()} - The source info (for registered clients).</li>
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
* <li>{@link #getEventTime()} - The event time.</li>
- * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #getText()} - The text of the source's sub-tree.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
* </ul>
* </p>
* <p>
* <b>Window content changed</b> - represents the event of change in the
* content of a window. This change can be adding/removing view, changing
* a view size, etc.</br>
+ * </p>
* <p>
* <strong>Note:</strong> This event is fired only for the window source of the
- * last accessibility event different from {@link #TYPE_NOTIFICATION_STATE_CHANGED})
+ * last accessibility event different from {@link #TYPE_NOTIFICATION_STATE_CHANGED}
* and its purpose is to notify clients that the content of the user interaction
- * window has changed.
- * </p>
+ * window has changed.</br>
* <em>Type:</em> {@link #TYPE_WINDOW_CONTENT_CHANGED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <li>{@link #getSource()} - The source info (for registered clients).</li>
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
* <li>{@link #getEventTime()} - The event time.</li>
* </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
+ * </p>
* <p>
* <b>NOTIFICATION TYPES</b></br>
+ * </p>
* <p>
* <b>Notification state changed</b> - represents the event showing
- * {@link android.app.Notification}.
+ * {@link android.app.Notification}.</br>
* <em>Type:</em> {@link #TYPE_NOTIFICATION_STATE_CHANGED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
* <li>{@link #getEventTime()} - The event time.</li>
- * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #getText()} - The text of the source's sub-tree.</li>
* <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}.</li>
+ * <li>{@link #getText()} - Text for providing more context.</li>
* </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
+ * </p>
+ * <p>
+ * <b>EXPLORATION TYPES</b></br>
+ * </p>
+ * <p>
+ * <b>View hover enter</b> - represents the event of beginning to hover
+ * over a {@link android.view.View}. The hover may be generated via
+ * exploring the screen by touch or via a pointing device.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_HOVER_ENTER}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source's sub-tree.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
+ * </ul>
+ * </p>
+ * <b>View hover exit</b> - represents the event of stopping to hover
+ * over a {@link android.view.View}. The hover may be generated via
+ * exploring the screen by touch or via a pointing device.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_HOVER_EXIT}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source's sub-tree.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * <b>Touch exploration gesture start</b> - represents the event of starting a touch
+ * exploring gesture.</br>
+ * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_START}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
+ * </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
+ * </p>
+ * <p>
+ * <b>Touch exploration gesture end</b> - represents the event of ending a touch
+ * exploring gesture.</br>
+ * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_END}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
+ * </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
* </p>
* <p>
* <b>Security note</b>
@@ -254,6 +394,7 @@
* Since an event contains the text of its source privacy can be compromised by leaking
* sensitive information such as passwords. To address this issue any event fired in response
* to manipulation of a PASSWORD field does NOT CONTAIN the text of the password.
+ * </p>
*
* @see android.view.accessibility.AccessibilityManager
* @see android.accessibilityservice.AccessibilityService
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index a4b4e78..61c5dd4 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -881,20 +881,14 @@
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- final int eventType = event.getEventType();
- switch (eventType) {
- case AccessibilityEvent.TYPE_VIEW_SCROLLED:
- // Do not populate the text of scroll events.
- return true;
- case AccessibilityEvent.TYPE_VIEW_FOCUSED:
- // This is an exceptional case which occurs when a window gets the
- // focus and sends a focus event via its focused child to announce
- // current focus/selection. AdapterView fires selection but not focus
- // events so we change the event type here.
- if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
- event.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED);
- }
- break;
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
+ // This is an exceptional case which occurs when a window gets the
+ // focus and sends a focus event via its focused child to announce
+ // current focus/selection. AdapterView fires selection but not focus
+ // events so we change the event type here.
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
+ event.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED);
+ }
}
View selectedView = getSelectedView();
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 84ebec3..63a0870 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -25,6 +25,7 @@
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Handler;
+import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.AttributeSet;
import android.view.View;
@@ -228,6 +229,8 @@
mMinutes = minute + second / 60.0f;
mHour = hour + mMinutes / 60.0f;
mChanged = true;
+
+ updateContentDescription(mCalendar);
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -243,4 +246,11 @@
invalidate();
}
};
+
+ private void updateContentDescription(Time time) {
+ final int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_24HOUR;
+ String contentDescription = DateUtils.formatDateTime(mContext,
+ time.toMillis(false), flags);
+ setContentDescription(contentDescription);
+ }
}
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index 3f5b571c..a0eba9a 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -371,16 +371,6 @@
}
}
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- // Do not append text content to scroll events they are fired frequently
- // and the client has already received another event type with the text.
- if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
- super.dispatchPopulateAccessibilityEvent(event);
- }
- return false;
- }
-
/**
* Tracks a motion scroll. In reality, this is used to do just about any
* movement to items (touch scroll, arrow-key scroll, set an item as selected).
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 1bbc501..324dfd7 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -725,16 +725,6 @@
event.setScrollable(true);
}
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- // Do not append text content to scroll events they are fired frequently
- // and the client has already received another event type with the text.
- if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
- super.dispatchPopulateAccessibilityEvent(event);
- }
- return false;
- }
-
private int getScrollRange() {
int scrollRange = 0;
if (getChildCount() > 0) {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 61ea5c9..3ac4e80 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -730,16 +730,6 @@
event.setScrollable(true);
}
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- // Do not append text content to scroll events they are fired frequently
- // and the client has already received another event type with the text.
- if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
- super.dispatchPopulateAccessibilityEvent(event);
- }
- return false;
- }
-
private int getScrollRange() {
int scrollRange = 0;
if (getChildCount() > 0) {
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 772c129..ce17184 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -165,6 +165,7 @@
@Override
public void onGetSuggestions(SuggestionsInfo[] results) {
+ final Editable editable = (Editable) mTextView.getText();
for (int i = 0; i < results.length; i++) {
SuggestionsInfo suggestionsInfo = results[i];
if (suggestionsInfo.getCookie() != mCookie) continue;
@@ -178,18 +179,19 @@
boolean looksLikeTypo =
((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) > 0);
+ SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j];
if (!isInDictionary && looksLikeTypo) {
- createMisspelledSuggestionSpan(suggestionsInfo, mSpellCheckSpans[j]);
+ createMisspelledSuggestionSpan(editable, suggestionsInfo, spellCheckSpan);
}
+ editable.removeSpan(spellCheckSpan);
break;
}
}
}
}
- private void createMisspelledSuggestionSpan(SuggestionsInfo suggestionsInfo,
+ private void createMisspelledSuggestionSpan(Editable editable, SuggestionsInfo suggestionsInfo,
SpellCheckSpan spellCheckSpan) {
- final Editable editable = (Editable) mTextView.getText();
final int start = editable.getSpanStart(spellCheckSpan);
final int end = editable.getSpanEnd(spellCheckSpan);
@@ -251,6 +253,5 @@
// TODO limit to the word rectangle region
mTextView.invalidate();
- editable.removeSpan(spellCheckSpan);
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5edb47c..17f0e05 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7780,7 +7780,7 @@
// Iterate over the newly added text and schedule new SpellCheckSpans
while (wordStart <= shiftedEnd) {
- if (wordEnd >= shiftedStart) {
+ if (wordEnd >= shiftedStart && wordEnd > wordStart) {
// A new word has been created across the interval boundaries. Remove previous spans
if (wordStart < shiftedStart && wordEnd > shiftedStart) {
removeSpansAt(start, spellCheckSpans, text);
@@ -8925,10 +8925,10 @@
// If a URLSpan (web address, email, phone...) is found at that position, select it.
URLSpan[] urlSpans = ((Spanned) mText).getSpans(minOffset, maxOffset, URLSpan.class);
- if (urlSpans.length == 1) {
- URLSpan url = urlSpans[0];
- selectionStart = ((Spanned) mText).getSpanStart(url);
- selectionEnd = ((Spanned) mText).getSpanEnd(url);
+ if (urlSpans.length >= 1) {
+ URLSpan urlSpan = urlSpans[0];
+ selectionStart = ((Spanned) mText).getSpanStart(urlSpan);
+ selectionEnd = ((Spanned) mText).getSpanEnd(urlSpan);
} else {
final int shift = prepareWordIterator(minOffset, maxOffset);
@@ -8939,10 +8939,42 @@
selectionEnd = mWordIterator.getEnd(maxOffset - shift);
if (selectionEnd == BreakIterator.DONE) return false;
selectionEnd += shift;
+
+ if (selectionStart == selectionEnd) {
+ // Possible when the word iterator does not properly handle the text's language
+ long range = getCharRange(selectionStart);
+ selectionStart = extractRangeStartFromLong(range);
+ selectionEnd = extractRangeEndFromLong(range);
+ }
}
Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
- return true;
+ return selectionEnd > selectionStart;
+ }
+
+ private long getCharRange(int offset) {
+ final int textLength = mText.length();
+ if (offset + 1 < textLength) {
+ final char currentChar = mText.charAt(offset);
+ final char nextChar = mText.charAt(offset + 1);
+ if (Character.isSurrogatePair(currentChar, nextChar)) {
+ return packRangeInLong(offset, offset + 2);
+ }
+ }
+ if (offset < textLength) {
+ return packRangeInLong(offset, offset + 1);
+ }
+ if (offset - 2 >= 0) {
+ final char previousChar = mText.charAt(offset - 1);
+ final char previousPreviousChar = mText.charAt(offset - 2);
+ if (Character.isSurrogatePair(previousPreviousChar, previousChar)) {
+ return packRangeInLong(offset - 2, offset);
+ }
+ }
+ if (offset - 1 >= 0) {
+ return packRangeInLong(offset - 1, offset);
+ }
+ return packRangeInLong(offset, offset);
}
int prepareWordIterator(int start, int end) {
@@ -9330,7 +9362,7 @@
// Start a new selection
if (!handled) {
- handled = startSelectionActionMode();
+ vibrate = handled = startSelectionActionMode();
}
if (vibrate) {
@@ -9946,8 +9978,8 @@
suggestionInfo.text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// Add the text before and after the span.
- suggestionInfo.text.insert(0, mText.subSequence(unionStart, spanStart).toString());
- suggestionInfo.text.append(mText.subSequence(spanEnd, unionEnd).toString());
+ suggestionInfo.text.insert(0, mText.toString().substring(unionStart, spanStart));
+ suggestionInfo.text.append(mText.toString().substring(spanEnd, unionEnd));
}
@Override
@@ -9979,7 +10011,7 @@
hide();
return;
}
- final String originalText = mText.subSequence(spanStart, spanEnd).toString();
+ final String originalText = mText.toString().substring(spanStart, spanEnd);
if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) {
Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT);
@@ -10016,8 +10048,10 @@
if (!TextUtils.isEmpty(
suggestionInfo.suggestionSpan.getNotificationTargetClassName())) {
InputMethodManager imm = InputMethodManager.peekInstance();
- imm.notifySuggestionPicked(suggestionInfo.suggestionSpan, originalText,
- suggestionInfo.suggestionIndex);
+ if (imm != null) {
+ imm.notifySuggestionPicked(suggestionInfo.suggestionSpan, originalText,
+ suggestionInfo.suggestionIndex);
+ }
}
// Swap text content between actual text and Suggestion span
@@ -10037,7 +10071,7 @@
}
}
- // Move cursor at the end of the replacement word
+ // Move cursor at the end of the replaced word
Selection.setSelection(editable, spanEnd + lengthDifference);
}
@@ -10166,8 +10200,7 @@
if (!hasSelection()) {
// There may already be a selection on device rotation
- boolean currentWordSelected = selectCurrentWord();
- if (!currentWordSelected) {
+ if (!selectCurrentWord()) {
// No word found under cursor or text selection not permitted.
return false;
}
@@ -10248,7 +10281,8 @@
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- TypedArray styledAttributes = mContext.obtainStyledAttributes(R.styleable.Theme);
+ TypedArray styledAttributes = mContext.obtainStyledAttributes(
+ com.android.internal.R.styleable.SelectionModeDrawables);
boolean allowText = getContext().getResources().getBoolean(
com.android.internal.R.bool.config_allowActionMenuItemTextWithIcon);
@@ -10261,7 +10295,7 @@
if (!allowText) {
// Provide an icon, text will not be displayed on smaller screens.
selectAllIconId = styledAttributes.getResourceId(
- R.styleable.Theme_actionModeSelectAllDrawable, 0);
+ R.styleable.SelectionModeDrawables_actionModeSelectAllDrawable, 0);
}
menu.add(0, ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll).
@@ -10273,7 +10307,7 @@
if (canCut()) {
menu.add(0, ID_CUT, 0, com.android.internal.R.string.cut).
setIcon(styledAttributes.getResourceId(
- R.styleable.Theme_actionModeCutDrawable, 0)).
+ R.styleable.SelectionModeDrawables_actionModeCutDrawable, 0)).
setAlphabeticShortcut('x').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
@@ -10282,7 +10316,7 @@
if (canCopy()) {
menu.add(0, ID_COPY, 0, com.android.internal.R.string.copy).
setIcon(styledAttributes.getResourceId(
- R.styleable.Theme_actionModeCopyDrawable, 0)).
+ R.styleable.SelectionModeDrawables_actionModeCopyDrawable, 0)).
setAlphabeticShortcut('c').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
@@ -10291,7 +10325,7 @@
if (canPaste()) {
menu.add(0, ID_PASTE, 0, com.android.internal.R.string.paste).
setIcon(styledAttributes.getResourceId(
- R.styleable.Theme_actionModePasteDrawable, 0)).
+ R.styleable.SelectionModeDrawables_actionModePasteDrawable, 0)).
setAlphabeticShortcut('v').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 7444d46..f52e773 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -237,9 +237,7 @@
}
// set the content descriptions
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- setContentDescriptions();
- }
+ setContentDescriptions();
}
@Override
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 4a38775..2694aa2 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -24,11 +24,15 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.hardware.Camera;
+import android.hardware.Camera.CameraInfo;
import android.os.FileObserver;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.os.storage.IMountService;
import android.provider.Settings;
import android.security.KeyStore;
@@ -55,6 +59,8 @@
*/
public class LockPatternUtils {
+ private static final String OPTION_ENABLE_FACELOCK = "enable_facelock";
+
private static final String TAG = "LockPatternUtils";
private static final String SYSTEM_DIRECTORY = "/system/";
@@ -110,6 +116,7 @@
public static final String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
private final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
private final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled";
+ private final static String LOCKSCREEN_OPTIONS = "lockscreen.options";
public final static String LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK
= "lockscreen.biometric_weak_fallback";
@@ -339,12 +346,21 @@
*/
public int getActivePasswordQuality() {
int activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
- switch (getKeyguardStoredPasswordQuality()) {
+ // Note we don't want to use getKeyguardStoredPasswordQuality() because we want this to
+ // return biometric_weak if that is being used instead of the backup
+ int quality =
+ (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ switch (quality) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
if (isLockPatternEnabled()) {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
}
break;
+ case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK:
+ if (isBiometricWeakInstalled()) {
+ activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
+ }
+ break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
if (isLockPasswordEnabled()) {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
@@ -366,6 +382,7 @@
}
break;
}
+
return activePasswordQuality;
}
@@ -434,7 +451,7 @@
* Calls back SetupFaceLock to delete the gallery file when the lock type is changed
*/
void deleteGallery() {
- if(isBiometricEnabled()) {
+ if(usingBiometricWeak()) {
Intent intent = new Intent().setClassName("com.android.facelock",
"com.android.facelock.SetupFaceLock");
intent.putExtra("deleteGallery", true);
@@ -677,6 +694,9 @@
return quality;
}
+ /**
+ * @return true if the lockscreen method is set to biometric weak
+ */
public boolean usingBiometricWeak() {
int quality =
(int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
@@ -810,7 +830,7 @@
|| backupMode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
return savedPasswordExists() && (passwordEnabled ||
- (isBiometricEnabled() && backupEnabled));
+ (usingBiometricWeak() && backupEnabled));
}
/**
@@ -824,16 +844,36 @@
return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED)
&& (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
== DevicePolicyManager.PASSWORD_QUALITY_SOMETHING ||
- (isBiometricEnabled() && backupEnabled));
+ (usingBiometricWeak() && backupEnabled));
}
/**
- * @return Whether biometric weak lock is enabled.
+ * @return Whether biometric weak lock is installed and that the front facing camera exists
*/
- public boolean isBiometricEnabled() {
- // TODO: check if it's installed
- return getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
- == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
+ public boolean isBiometricWeakInstalled() {
+ // Check that the system flag was set
+ if (!OPTION_ENABLE_FACELOCK.equals(getString(LOCKSCREEN_OPTIONS))) {
+ return false;
+ }
+
+ // Check that it's installed
+ PackageManager pm = mContext.getPackageManager();
+ try {
+ pm.getPackageInfo("com.android.facelock", PackageManager.GET_ACTIVITIES);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+
+ // Check that the camera is enabled
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) {
+ return false;
+ }
+ if (getDevicePolicyManager().getCameraDisabled(null)) {
+ return false;
+ }
+
+
+ return true;
}
/**
diff --git a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
index 366b983..01df48a 100644
--- a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
+++ b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
@@ -48,11 +48,11 @@
private PasswordEntryKeyboard mSymbolsKeyboard;
private PasswordEntryKeyboard mSymbolsKeyboardShifted;
private PasswordEntryKeyboard mNumericKeyboard;
- private Context mContext;
- private View mTargetView;
- private KeyboardView mKeyboardView;
+ private final Context mContext;
+ private final View mTargetView;
+ private final KeyboardView mKeyboardView;
private long[] mVibratePattern;
- private Vibrator mVibrator;
+ private final Vibrator mVibrator;
public PasswordEntryKeyboardHelper(Context context, KeyboardView keyboardView, View targetView) {
this(context, keyboardView, targetView, true);
@@ -228,7 +228,7 @@
}
}
- private void handleBackspace() {
+ public void handleBackspace() {
sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
}
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 18bd754..da055fc 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -392,10 +392,20 @@
SkSafeUnref(ctable);
size_t size = bitmap->getSize();
+
+ android::Parcel::ReadableBlob blob;
+ android::status_t status = p->readBlob(size, &blob);
+ if (status) {
+ doThrowRE(env, "Could not read bitmap from parcel blob.");
+ delete bitmap;
+ return NULL;
+ }
+
bitmap->lockPixels();
- memcpy(bitmap->getPixels(), p->readInplace(size), size);
+ memcpy(bitmap->getPixels(), blob.data(), size);
bitmap->unlockPixels();
+ blob.release();
return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, density);
}
@@ -431,17 +441,24 @@
}
size_t size = bitmap->getSize();
+
+ android::Parcel::WritableBlob blob;
+ android::status_t status = p->writeBlob(size, &blob);
+ if (status) {
+ doThrowRE(env, "Could not write bitmap to parcel blob.");
+ return false;
+ }
+
bitmap->lockPixels();
- void* pDst = p->writeInplace(size);
-
const void* pSrc = bitmap->getPixels();
-
if (pSrc == NULL) {
- memset(pDst, 0, size);
+ memset(blob.data(), 0, size);
} else {
- memcpy(pDst, pSrc, size);
+ memcpy(blob.data(), pSrc, size);
}
bitmap->unlockPixels();
+
+ blob.release();
return true;
}
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 494a2b3..1718e74 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -697,6 +697,10 @@
LOGE("!!! FAILED BINDER TRANSACTION !!!");
//jniThrowException(env, "java/lang/OutOfMemoryError", "Binder transaction too large");
break;
+ case FDS_NOT_ALLOWED:
+ jniThrowException(env, "java/lang/RuntimeException",
+ "Not allowed to write file descriptors here");
+ break;
default:
LOGE("Unknown binder error code. 0x%x", err);
}
@@ -1275,7 +1279,7 @@
if (parcel != NULL) {
const status_t err = parcel->setDataSize(size);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1294,11 +1298,29 @@
if (parcel != NULL) {
const status_t err = parcel->setDataCapacity(size);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
+static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jobject clazz, jboolean allowFds)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ jboolean ret = JNI_TRUE;
+ if (parcel != NULL) {
+ ret = (jboolean)parcel->pushAllowFds(allowFds);
+ }
+ return ret;
+}
+
+static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jobject clazz, jboolean lastValue)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ parcel->restoreAllowFds((bool)lastValue);
+ }
+}
+
static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz,
jobject data, jint offset,
jint length)
@@ -1310,12 +1332,13 @@
const status_t err = parcel->writeInt32(length);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
+ return;
}
void* dest = parcel->writeInplace(length);
if (dest == NULL) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, NO_MEMORY);
return;
}
@@ -1333,7 +1356,7 @@
if (parcel != NULL) {
const status_t err = parcel->writeInt32(val);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1344,7 +1367,7 @@
if (parcel != NULL) {
const status_t err = parcel->writeInt64(val);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1355,7 +1378,7 @@
if (parcel != NULL) {
const status_t err = parcel->writeFloat(val);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1366,7 +1389,7 @@
if (parcel != NULL) {
const status_t err = parcel->writeDouble(val);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1386,7 +1409,7 @@
err = parcel->writeString16(NULL, 0);
}
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1397,7 +1420,7 @@
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1409,7 +1432,7 @@
const status_t err =
parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1717,7 +1740,10 @@
return;
}
- (void) thisParcel->appendFrom(otherParcel, offset, length);
+ status_t err = thisParcel->appendFrom(otherParcel, offset, length);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
}
static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz)
@@ -1792,6 +1818,8 @@
{"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize},
{"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition},
{"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity},
+ {"pushAllowFds", "(Z)Z", (void*)android_os_Parcel_pushAllowFds},
+ {"restoreAllowFds", "(Z)V", (void*)android_os_Parcel_restoreAllowFds},
{"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative},
{"writeInt", "(I)V", (void*)android_os_Parcel_writeInt},
{"writeLong", "(J)V", (void*)android_os_Parcel_writeLong},
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9755f22..18194ee 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -263,6 +263,23 @@
android:label="@string/permlab_writeProfile"
android:description="@string/permdesc_writeProfile" />
+ <!-- Allows an application to read from the user's social stream.
+ @hide -->
+ <permission android:name="android.permission.READ_SOCIAL_STREAM"
+ android:permissionGroup="android.permission-group.PERSONAL_INFO"
+ android:protectionLevel="dangerous"
+ android:label="@string/permlab_readSocialStream"
+ android:description="@string/permdesc_readSocialStream" />
+
+ <!-- Allows an application to write (but not read) the user's
+ social stream data.
+ @hide -->
+ <permission android:name="android.permission.WRITE_SOCIAL_STREAM"
+ android:permissionGroup="android.permission-group.PERSONAL_INFO"
+ android:protectionLevel="dangerous"
+ android:label="@string/permlab_writeSocialStream"
+ android:description="@string/permdesc_writeSocialStream" />
+
<!-- Allows an application to read the user's calendar data. -->
<permission android:name="android.permission.READ_CALENDAR"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index 8bc5f34..e34822d 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -135,7 +135,8 @@
<LinearLayout
android:orientation="horizontal"
android:layout_width="270dip"
- android:layout_gravity="center_vertical">
+ android:layout_gravity="center_vertical"
+ android:background="@drawable/lockscreen_password_field_dark">
<EditText android:id="@+id/passwordEntry"
android:layout_height="wrap_content"
@@ -148,11 +149,23 @@
android:textSize="24sp"
android:minEms="8"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:background="@drawable/lockscreen_password_field_dark"
+ android:background="@null"
android:textColor="?android:attr/textColorPrimary"
android:imeOptions="flagNoFullscreen|actionDone"
/>
+ <!-- This delete button is only visible for numeric PIN entry -->
+ <ImageButton android:id="@+id/pinDel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@android:drawable/ic_input_delete"
+ android:clickable="true"
+ android:padding="8dip"
+ android:layout_gravity="center"
+ android:background="?android:attr/selectableItemBackground"
+ android:visibility="gone"
+ />
+
<ImageView android:id="@+id/switch_ime_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 2a66d7d..e1280ba 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -95,9 +95,12 @@
/>
<!-- Password entry field -->
+ <!-- Note: the entire container is styled to look like the edit field,
+ since the backspace/IME switcher looks better inside -->
<LinearLayout
android:layout_gravity="center_vertical|fill_horizontal"
android:orientation="horizontal"
+ android:background="@drawable/lockscreen_password_field_dark"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip">
@@ -110,12 +113,24 @@
android:textStyle="normal"
android:inputType="textPassword"
android:textSize="36sp"
- android:background="@drawable/lockscreen_password_field_dark"
+ android:background="@null"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#ffffffff"
android:imeOptions="actionDone"
/>
+ <!-- This delete button is only visible for numeric PIN entry -->
+ <ImageButton android:id="@+id/pinDel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@android:drawable/ic_input_delete"
+ android:clickable="true"
+ android:padding="8dip"
+ android:layout_gravity="center_vertical"
+ android:background="?android:attr/selectableItemBackground"
+ android:visibility="gone"
+ />
+
<ImageView android:id="@+id/switch_ime_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index c990125..a27abb3 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3181,6 +3181,12 @@
<!-- Base text color, typeface, size, and style. -->
<attr name="textAppearance" />
</declare-styleable>
+ <declare-styleable name="SelectionModeDrawables">
+ <attr name="actionModeSelectAllDrawable" />
+ <attr name="actionModeCutDrawable" />
+ <attr name="actionModeCopyDrawable" />
+ <attr name="actionModePasteDrawable" />
+ </declare-styleable>
<declare-styleable name="SuggestionSpan">
<attr name="textUnderlineColor" />
<attr name="textUnderlineThickness" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 1e0151a..9208efe 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -941,6 +941,19 @@
information. This means other applications can identify you and send your profile
information to others.</string>
+ <!-- Title of the read social stream permission, listed so the user can decide whether to allow the application to read information from the user's social stream. [CHAR LIMIT=30] -->
+ <string name="permlab_readSocialStream" product="default">read your social stream</string>
+ <string name="permdesc_readSocialStream" product="default">Allows the application to access
+ and sync social updates from you and your friends. Malicious apps can use this to read
+ private communications between you and your friends on social networks.</string>
+
+ <!-- Title of the write social stream permission, listed so the user can decide whether to allow the application to write information to the user's social stream. [CHAR LIMIT=30] -->
+ <string name="permlab_writeSocialStream" product="default">write to your social stream</string>
+ <string name="permdesc_writeSocialStream" product="default">Allows the application to display
+ social updates from your friends. Malicious apps can use this to pretend to be a friend
+ and trick you into revealing passwords or other confidential information.</string>
+
+
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_readCalendar">read calendar events plus confidential information</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -3316,4 +3329,4 @@
<!-- Delimeter used between each item in a textual list; for example "Alpha, Beta". [CHAR LIMIT=3] -->
<string name="list_delimeter">", "</string>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/core/res/res/xml/password_kbd_numeric.xml b/core/res/res/xml/password_kbd_numeric.xml
index 2fd5aa0..560f867 100755
--- a/core/res/res/xml/password_kbd_numeric.xml
+++ b/core/res/res/xml/password_kbd_numeric.xml
@@ -49,12 +49,10 @@
</Row>
<Row android:rowEdgeFlags="bottom">
+ <Key android:codes="48" android:keyIcon="@drawable/sym_keyboard_num0_no_plus"
+ android:keyWidth="66.66%p" android:keyEdgeFlags="left"/>
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
- android:keyEdgeFlags="left"/>
- <Key android:codes="48" android:keyIcon="@drawable/sym_keyboard_num0_no_plus"/>
- <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
- android:iconPreview="@drawable/sym_keyboard_feedback_delete"
- android:isRepeatable="true" android:keyEdgeFlags="right"/>
+ android:keyEdgeFlags="right"/>
</Row>
</Keyboard>
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index c36685d..d78d2ef 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -18,6 +18,8 @@
import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.SET_FOREGROUND;
+import static android.net.NetworkStats.SET_ALL;
+import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
@@ -176,8 +178,63 @@
assertEquals(64L, uidTag.getTotalBytes());
}
+ public void testGroupedByIfaceEmpty() throws Exception {
+ final NetworkStats uidStats = new NetworkStats(TEST_START, 3);
+ final NetworkStats grouped = uidStats.groupedByIface();
+
+ assertEquals(0, uidStats.size());
+ assertEquals(0, grouped.size());
+ }
+
+ public void testGroupedByIfaceAll() throws Exception {
+ final NetworkStats uidStats = new NetworkStats(TEST_START, 3)
+ .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
+ .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, 128L, 8L, 0L, 2L, 20L);
+ final NetworkStats grouped = uidStats.groupedByIface();
+
+ assertEquals(2, uidStats.size());
+ assertEquals(1, grouped.size());
+
+ assertValues(grouped, 0, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, 256L, 16L, 0L, 4L, 0L);
+ }
+
+ public void testGroupedByIface() throws Exception {
+ final NetworkStats uidStats = new NetworkStats(TEST_START, 3)
+ .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
+ .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 64L, 4L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 512L, 32L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 128L, 8L, 0L, 0L, 0L);
+
+ final NetworkStats grouped = uidStats.groupedByIface();
+
+ assertEquals(6, uidStats.size());
+
+ assertEquals(2, grouped.size());
+ assertValues(grouped, 0, TEST_IFACE, UID_ALL, SET_ALL, TAG_NONE, 256L, 16L, 0L, 2L, 0L);
+ assertValues(grouped, 1, TEST_IFACE2, UID_ALL, SET_ALL, TAG_NONE, 1024L, 64L, 0L, 0L, 0L);
+ }
+
+ public void testAddAllValues() {
+ final NetworkStats first = new NetworkStats(TEST_START, 5)
+ .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
+
+ final NetworkStats second = new NetworkStats(TEST_START, 2)
+ .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
+
+ first.combineAllValues(second);
+
+ assertEquals(3, first.size());
+ assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 64L, 0L, 0L, 0L, 0L);
+ assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
+ assertValues(first, 2, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
+ }
+
private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set,
- int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) {
+ int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
final NetworkStats.Entry entry = stats.getValues(index, null);
assertEquals(iface, entry.iface);
assertEquals(uid, entry.uid);
diff --git a/data/sounds/AudioPackage7.mk b/data/sounds/AudioPackage7.mk
index 16171dc..9983f38 100755
--- a/data/sounds/AudioPackage7.mk
+++ b/data/sounds/AudioPackage7.mk
@@ -27,17 +27,24 @@
$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
$(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
$(LOCAL_PATH)/notifications/ogg/Altair.ogg:system/media/audio/notifications/Altair.ogg \
- $(LOCAL_PATH)/notifications/ogg/Antares.ogg:system/media/audio/notifications/Antares.ogg \
- $(LOCAL_PATH)/notifications/ogg/Deneb.ogg:system/media/audio/notifications/Deneb.ogg \
- $(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
- $(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
- $(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
$(LOCAL_PATH)/notifications/ogg/Betelgeuse.ogg:system/media/audio/notifications/Betelgeuse.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
+ $(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Deneb.ogg:system/media/audio/notifications/Deneb.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
$(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
$(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Acheron.ogg:system/media/audio/ringtones/Acheron.ogg \
$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
$(LOCAL_PATH)/ringtones/ogg/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
$(LOCAL_PATH)/ringtones/ogg/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/CanisMajor.ogg:system/media/audio/ringtones/CanisMajor.ogg \
$(LOCAL_PATH)/ringtones/ogg/Carina.ogg:system/media/audio/ringtones/Carina.ogg \
$(LOCAL_PATH)/ringtones/ogg/Cassiopeia.ogg:system/media/audio/ringtones/Cassiopeia.ogg \
$(LOCAL_PATH)/ringtones/ogg/Centaurus.ogg:system/media/audio/ringtones/Centaurus.ogg \
@@ -45,8 +52,10 @@
$(LOCAL_PATH)/ringtones/ogg/Draco.ogg:system/media/audio/ringtones/Draco.ogg \
$(LOCAL_PATH)/ringtones/ogg/Hydra.ogg:system/media/audio/ringtones/Hydra.ogg \
$(LOCAL_PATH)/ringtones/ogg/Machina.ogg:system/media/audio/ringtones/Machina.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Nasqueron.ogg:system/media/audio/ringtones/Nasqueron.ogg \
$(LOCAL_PATH)/ringtones/ogg/Orion.ogg:system/media/audio/ringtones/Orion.ogg \
$(LOCAL_PATH)/ringtones/ogg/Pegasus.ogg:system/media/audio/ringtones/Pegasus.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Perseus.ogg:system/media/audio/ringtones/Perseus.ogg \
$(LOCAL_PATH)/ringtones/ogg/Pyxis.ogg:system/media/audio/ringtones/Pyxis.ogg \
$(LOCAL_PATH)/ringtones/ogg/Rigel.ogg:system/media/audio/ringtones/Rigel.ogg \
$(LOCAL_PATH)/ringtones/ogg/Scarabaeus.ogg:system/media/audio/ringtones/Scarabaeus.ogg \
diff --git a/data/sounds/notifications/ogg/Arcturus.ogg b/data/sounds/notifications/ogg/Arcturus.ogg
new file mode 100644
index 0000000..8b83285
--- /dev/null
+++ b/data/sounds/notifications/ogg/Arcturus.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Capella.ogg b/data/sounds/notifications/ogg/Capella.ogg
new file mode 100755
index 0000000..88a955d
--- /dev/null
+++ b/data/sounds/notifications/ogg/Capella.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/CetiAlpha.ogg b/data/sounds/notifications/ogg/CetiAlpha.ogg
new file mode 100644
index 0000000..cd09526
--- /dev/null
+++ b/data/sounds/notifications/ogg/CetiAlpha.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Polaris.ogg b/data/sounds/notifications/ogg/Polaris.ogg
new file mode 100755
index 0000000..0f63a65
--- /dev/null
+++ b/data/sounds/notifications/ogg/Polaris.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Procyon.ogg b/data/sounds/notifications/ogg/Procyon.ogg
new file mode 100755
index 0000000..e5ffcdb
--- /dev/null
+++ b/data/sounds/notifications/ogg/Procyon.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Vega.ogg b/data/sounds/notifications/ogg/Vega.ogg
new file mode 100644
index 0000000..7cdbf21
--- /dev/null
+++ b/data/sounds/notifications/ogg/Vega.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Acheron.ogg b/data/sounds/ringtones/ogg/Acheron.ogg
new file mode 100644
index 0000000..67d7388
--- /dev/null
+++ b/data/sounds/ringtones/ogg/Acheron.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Nasqueron.ogg b/data/sounds/ringtones/ogg/Nasqueron.ogg
new file mode 100644
index 0000000..ae1a725
--- /dev/null
+++ b/data/sounds/ringtones/ogg/Nasqueron.ogg
Binary files differ
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index bfe13f0..3fa2acb 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -38,6 +38,9 @@
class Parcel
{
public:
+ class ReadableBlob;
+ class WritableBlob;
+
Parcel();
~Parcel();
@@ -46,7 +49,7 @@
size_t dataAvail() const;
size_t dataPosition() const;
size_t dataCapacity() const;
-
+
status_t setDataSize(size_t size);
void setDataPosition(size_t pos) const;
status_t setDataCapacity(size_t size);
@@ -56,6 +59,9 @@
status_t appendFrom(const Parcel *parcel,
size_t start, size_t len);
+ bool pushAllowFds(bool allowFds);
+ void restoreAllowFds(bool lastValue);
+
bool hasFileDescriptors() const;
// Writes the RPC header.
@@ -109,7 +115,13 @@
// Place a file descriptor into the parcel. A dup of the fd is made, which
// will be closed once the parcel is destroyed.
status_t writeDupFileDescriptor(int fd);
-
+
+ // Writes a blob to the parcel.
+ // If the blob is small, then it is stored in-place, otherwise it is
+ // transferred by way of an anonymous shared memory region.
+ // The caller should call release() on the blob after writing its contents.
+ status_t writeBlob(size_t len, WritableBlob* outBlob);
+
status_t writeObject(const flat_binder_object& val, bool nullMetaData);
// Like Parcel.java's writeNoException(). Just writes a zero int32.
@@ -157,7 +169,11 @@
// Retrieve a file descriptor from the parcel. This returns the raw fd
// in the parcel, which you do not own -- use dup() to get your own copy.
int readFileDescriptor() const;
-
+
+ // Reads a blob from the parcel.
+ // The caller should call release() on the blob after reading its contents.
+ status_t readBlob(size_t len, ReadableBlob* outBlob) const;
+
const flat_binder_object* readObject(bool nullMetaData) const;
// Explicitly close all file descriptors in the parcel.
@@ -177,7 +193,7 @@
release_func relFunc, void* relCookie);
void print(TextOutput& to, uint32_t flags = 0) const;
-
+
private:
Parcel(const Parcel& o);
Parcel& operator=(const Parcel& o);
@@ -212,9 +228,40 @@
mutable bool mFdsKnown;
mutable bool mHasFds;
+ bool mAllowFds;
release_func mOwner;
void* mOwnerCookie;
+
+ class Blob {
+ public:
+ Blob();
+ ~Blob();
+
+ void release();
+ inline size_t size() const { return mSize; }
+
+ protected:
+ void init(bool mapped, void* data, size_t size);
+ void clear();
+
+ bool mMapped;
+ void* mData;
+ size_t mSize;
+ };
+
+public:
+ class ReadableBlob : public Blob {
+ friend class Parcel;
+ public:
+ inline const void* data() const { return mData; }
+ };
+
+ class WritableBlob : public Blob {
+ friend class Parcel;
+ public:
+ inline void* data() { return mData; }
+ };
};
// ---------------------------------------------------------------------------
diff --git a/include/utils/Errors.h b/include/utils/Errors.h
index 81f818b..0b75b19 100644
--- a/include/utils/Errors.h
+++ b/include/utils/Errors.h
@@ -72,6 +72,7 @@
TIMED_OUT = 0x80000005,
UNKNOWN_TRANSACTION = 0x80000006,
#endif
+ FDS_NOT_ALLOWED = 0x80000007,
};
// Restore define; enumeration is in "android" namespace, so the value defined
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index a0fc4d0..608877e 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -30,12 +30,14 @@
#include <utils/TextOutput.h>
#include <utils/misc.h>
#include <utils/Flattenable.h>
+#include <cutils/ashmem.h>
#include <private/binder/binder_module.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
+#include <sys/mman.h>
#ifndef INT32_MAX
#define INT32_MAX ((int32_t)(2147483647))
@@ -54,6 +56,9 @@
// Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER
#define EX_HAS_REPLY_HEADER -128
+// Maximum size of a blob to transfer in-place.
+static const size_t IN_PLACE_BLOB_LIMIT = 40 * 1024;
+
// XXX This can be made public if we want to provide
// support for typed data.
struct small_flat_data
@@ -399,6 +404,8 @@
mDataPos += len;
mDataSize += len;
+ err = NO_ERROR;
+
if (numObjects > 0) {
// grow objects
if (mObjectsCapacity < mObjectsSize + numObjects) {
@@ -430,11 +437,28 @@
flat->handle = dup(flat->handle);
flat->cookie = (void*)1;
mHasFds = mFdsKnown = true;
+ if (!mAllowFds) {
+ err = FDS_NOT_ALLOWED;
+ }
}
}
}
- return NO_ERROR;
+ return err;
+}
+
+bool Parcel::pushAllowFds(bool allowFds)
+{
+ const bool origValue = mAllowFds;
+ if (!allowFds) {
+ mAllowFds = false;
+ }
+ return origValue;
+}
+
+void Parcel::restoreAllowFds(bool lastValue)
+{
+ mAllowFds = lastValue;
}
bool Parcel::hasFileDescriptors() const
@@ -706,6 +730,54 @@
return writeObject(obj, true);
}
+status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob)
+{
+ status_t status;
+
+ if (!mAllowFds || len <= IN_PLACE_BLOB_LIMIT) {
+ LOGV("writeBlob: write in place");
+ status = writeInt32(0);
+ if (status) return status;
+
+ void* ptr = writeInplace(len);
+ if (!ptr) return NO_MEMORY;
+
+ outBlob->init(false /*mapped*/, ptr, len);
+ return NO_ERROR;
+ }
+
+ LOGV("writeBlob: write to ashmem");
+ int fd = ashmem_create_region("Parcel Blob", len);
+ if (fd < 0) return NO_MEMORY;
+
+ int result = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
+ if (result < 0) {
+ status = -result;
+ } else {
+ void* ptr = ::mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (ptr == MAP_FAILED) {
+ status = -errno;
+ } else {
+ result = ashmem_set_prot_region(fd, PROT_READ);
+ if (result < 0) {
+ status = -result;
+ } else {
+ status = writeInt32(1);
+ if (!status) {
+ status = writeFileDescriptor(fd);
+ if (!status) {
+ outBlob->init(true /*mapped*/, ptr, len);
+ return NO_ERROR;
+ }
+ }
+ }
+ }
+ ::munmap(ptr, len);
+ }
+ ::close(fd);
+ return status;
+}
+
status_t Parcel::write(const Flattenable& val)
{
status_t err;
@@ -759,6 +831,9 @@
// remember if it's a file descriptor
if (val.type == BINDER_TYPE_FD) {
+ if (!mAllowFds) {
+ return FDS_NOT_ALLOWED;
+ }
mHasFds = mFdsKnown = true;
}
@@ -1025,6 +1100,32 @@
return BAD_TYPE;
}
+status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const
+{
+ int32_t useAshmem;
+ status_t status = readInt32(&useAshmem);
+ if (status) return status;
+
+ if (!useAshmem) {
+ LOGV("readBlob: read in place");
+ const void* ptr = readInplace(len);
+ if (!ptr) return BAD_VALUE;
+
+ outBlob->init(false /*mapped*/, const_cast<void*>(ptr), len);
+ return NO_ERROR;
+ }
+
+ LOGV("readBlob: read from ashmem");
+ int fd = readFileDescriptor();
+ if (fd == int(BAD_TYPE)) return BAD_VALUE;
+
+ void* ptr = ::mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+ if (!ptr) return NO_MEMORY;
+
+ outBlob->init(true /*mapped*/, ptr, len);
+ return NO_ERROR;
+}
+
status_t Parcel::read(Flattenable& val) const
{
// size
@@ -1283,6 +1384,7 @@
mNextObjectHint = 0;
mHasFds = false;
mFdsKnown = true;
+ mAllowFds = true;
return NO_ERROR;
}
@@ -1434,6 +1536,7 @@
mNextObjectHint = 0;
mHasFds = false;
mFdsKnown = true;
+ mAllowFds = true;
mOwner = NULL;
}
@@ -1452,4 +1555,33 @@
mFdsKnown = true;
}
+// --- Parcel::Blob ---
+
+Parcel::Blob::Blob() :
+ mMapped(false), mData(NULL), mSize(0) {
+}
+
+Parcel::Blob::~Blob() {
+ release();
+}
+
+void Parcel::Blob::release() {
+ if (mMapped && mData) {
+ ::munmap(mData, mSize);
+ }
+ clear();
+}
+
+void Parcel::Blob::init(bool mapped, void* data, size_t size) {
+ mMapped = mapped;
+ mData = data;
+ mSize = size;
+}
+
+void Parcel::Blob::clear() {
+ mMapped = false;
+ mData = NULL;
+ mSize = 0;
+}
+
}; // namespace android
diff --git a/libs/rs/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp
index 0755fb7..5fd5c35 100644
--- a/libs/rs/driver/rsdBcc.cpp
+++ b/libs/rs/driver/rsdBcc.cpp
@@ -302,7 +302,10 @@
DrvScript *drv = (DrvScript *)s->mHal.drv;
// We only support slot 0 (root) at this point in time.
rsAssert(slot == 0);
- mtls.sig = drv->mExportForEachSignatureList[slot];
+ mtls.sig = 0x1f; // temp fix for old apps, full table in slang_rs_export_foreach.cpp
+ if (drv->mExportForEachSignatureList) {
+ mtls.sig = drv->mExportForEachSignatureList[slot];
+ }
if (ain) {
mtls.dimX = ain->getType()->getDimX();
mtls.dimY = ain->getType()->getDimY();
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d0ece6c..830506c 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -30,7 +30,7 @@
<!-- Size of application thumbnail -->
<dimen name="status_bar_recents_thumbnail_width">164dp</dimen>
- <dimen name="status_bar_recents_thumbnail_height">164dp</dimen>
+ <dimen name="status_bar_recents_thumbnail_height">145dp</dimen>
<!-- Size of application label text -->
<dimen name="status_bar_recents_app_label_text_size">16dip</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index ca9e273..e3f5cdb 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -60,6 +60,7 @@
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ImageView.ScaleType;
import com.android.systemui.R;
import com.android.systemui.statusbar.StatusBar;
@@ -556,7 +557,7 @@
if (v.getTag() instanceof ViewHolder) {
ViewHolder h = (ViewHolder)v.getTag();
if (h.activityDescription == ad) {
- if (DEBUG) Log.v(TAG, "Updatating thumbnail #" + index + " in "
+ if (DEBUG) Log.v(TAG, "Updating thumbnail #" + index + " in "
+ h.activityDescription
+ ": " + ad.getThumbnail());
h.iconView.setImageDrawable(ad.getIcon());
@@ -578,6 +579,15 @@
// that this now covers, to improve scrolling speed.
// That can't be done until the anim is complete though.
h.thumbnailViewImage.setImageBitmap(thumbnail);
+
+ // scale to fill up the full width
+ Matrix scaleMatrix = new Matrix();
+ float thumbnailViewWidth = h.thumbnailViewImage.getWidth();
+ float scale = thumbnailViewWidth / thumbnail.getWidth();
+ scaleMatrix.setScale(scale, scale);
+ h.thumbnailViewImage.setScaleType(ScaleType.MATRIX);
+ h.thumbnailViewImage.setImageMatrix(scaleMatrix);
+
if (anim) {
h.thumbnailViewImage.setAnimation(AnimationUtils.loadAnimation(
mContext, R.anim.recent_appear));
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 886997c..c25e3ca 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -147,8 +147,16 @@
*/
private static final boolean ENABLE_INSECURE_STATUS_BAR_EXPAND = true;
+ /** The stream type that the lock sounds are tied to. */
+ private static final int MASTER_STREAM_TYPE = AudioManager.STREAM_RING;
+ /** Minimum volume for lock sounds, as a ratio of max MASTER_STREAM_TYPE */
+ final float MIN_LOCK_VOLUME = 0.05f;
+ /** Maximum volume for lock sounds, as a ratio of max MASTER_STREAM_TYPE */
+ final float MAX_LOCK_VOLUME = 0.4f;
+
private Context mContext;
private AlarmManager mAlarmManager;
+ private AudioManager mAudioManager;
private StatusBarManager mStatusBarManager;
private boolean mShowLockIcon;
private boolean mShowingLockIcon;
@@ -255,6 +263,7 @@
private int mLockSoundId;
private int mUnlockSoundId;
private int mLockSoundStreamId;
+ private int mMasterStreamMaxVolume;
public KeyguardViewMediator(Context context, PhoneWindowManager callback,
LocalPowerManager powerManager) {
@@ -1061,13 +1070,33 @@
}
final ContentResolver cr = mContext.getContentResolver();
- if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1)
- {
+ if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) {
final int whichSound = locked
? mLockSoundId
: mUnlockSoundId;
mLockSounds.stop(mLockSoundStreamId);
- mLockSoundStreamId = mLockSounds.play(whichSound, 1.0f, 1.0f, 1, 0, 1.0f);
+ // Init mAudioManager
+ if (mAudioManager == null) {
+ mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ if (mAudioManager == null) return;
+ mMasterStreamMaxVolume = mAudioManager.getStreamMaxVolume(MASTER_STREAM_TYPE);
+ }
+ // If the stream is muted, don't play the sound
+ if (mAudioManager.isStreamMute(MASTER_STREAM_TYPE)) return;
+
+ // Adjust the lock sound volume from a minimum of MIN_LOCK_VOLUME to a maximum
+ // of MAX_LOCK_VOLUME, relative to the maximum level of the MASTER_STREAM_TYPE volume.
+ float lockSoundVolume;
+ int masterStreamVolume = mAudioManager.getStreamVolume(MASTER_STREAM_TYPE);
+ if (masterStreamVolume == 0) {
+ return;
+ } else {
+ lockSoundVolume = MIN_LOCK_VOLUME + (MAX_LOCK_VOLUME - MIN_LOCK_VOLUME)
+ * ((float) masterStreamVolume / mMasterStreamMaxVolume);
+ }
+
+ mLockSoundStreamId = mLockSounds.play(whichSound, lockSoundVolume, lockSoundVolume, 1,
+ 0, 1.0f);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index f970ff3..ca5d274 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -531,7 +531,8 @@
((KeyguardScreen) mUnlockScreen).onResume();
}
- if (mLockPatternUtils.usingBiometricWeak()) {
+ if (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled()) {
mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW);
} else {
mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
@@ -1014,7 +1015,8 @@
// Binds to FaceLock service, but does not tell it to start
public void bindToFaceLock() {
- if (mLockPatternUtils.usingBiometricWeak()) {
+ if (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled()) {
if (!mBoundToFaceLockService) {
if (DEBUG) Log.d(TAG, "before bind to FaceLock service");
mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
@@ -1030,7 +1032,8 @@
// Tells FaceLock to stop and then unbinds from the FaceLock service
public void stopAndUnbindFromFaceLock() {
- if (mLockPatternUtils.usingBiometricWeak()) {
+ if (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled()) {
stopFaceLock();
if (mBoundToFaceLockService) {
@@ -1079,7 +1082,8 @@
// Tells the FaceLock service to start displaying its UI and perform recognition
public void startFaceLock(IBinder windowToken, int x, int y, int h, int w)
{
- if (mLockPatternUtils.usingBiometricWeak()) {
+ if (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled()) {
synchronized (mFaceLockServiceRunningLock) {
if (!mFaceLockServiceRunning) {
if (DEBUG) Log.d(TAG, "Starting FaceLock");
@@ -1099,7 +1103,8 @@
// Tells the FaceLock service to stop displaying its UI and stop recognition
public void stopFaceLock()
{
- if (mLockPatternUtils.usingBiometricWeak()) {
+ if (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled()) {
// Note that attempting to stop FaceLock when it's not running is not an issue.
// FaceLock can return, which stops it and then we try to stop it when the
// screen is turned off. That's why we check.
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index 6d2f2f2..ec0072c 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -60,19 +60,18 @@
private final KeyguardUpdateMonitor mUpdateMonitor;
private final KeyguardScreenCallback mCallback;
- private boolean mIsAlpha;
+ private final boolean mIsAlpha;
- private EditText mPasswordEntry;
- private LockPatternUtils mLockPatternUtils;
- private PasswordEntryKeyboardView mKeyboardView;
- private PasswordEntryKeyboardHelper mKeyboardHelper;
+ private final EditText mPasswordEntry;
+ private final LockPatternUtils mLockPatternUtils;
+ private final PasswordEntryKeyboardView mKeyboardView;
+ private final PasswordEntryKeyboardHelper mKeyboardHelper;
- private int mCreationOrientation;
- private int mCreationHardKeyboardHidden;
- private CountDownTimer mCountdownTimer;
+ private final int mCreationOrientation;
+ private final int mCreationHardKeyboardHidden;
- private KeyguardStatusViewManager mStatusViewManager;
- private boolean mUseSystemIME = true; // TODO: Make configurable
+ private final KeyguardStatusViewManager mStatusViewManager;
+ private final boolean mUseSystemIME = true; // TODO: Make configurable
private boolean mResuming; // used to prevent poking the wakelock during onResume()
// To avoid accidental lockout due to events while the device in in the pocket, ignore
@@ -119,6 +118,19 @@
mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
mKeyboardView.setVisibility(mCreationHardKeyboardHidden
== Configuration.HARDKEYBOARDHIDDEN_NO ? View.INVISIBLE : View.VISIBLE);
+
+ // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
+ // not a separate view
+ View pinDelete = findViewById(R.id.pinDel);
+ if (pinDelete != null) {
+ pinDelete.setVisibility(View.VISIBLE);
+ pinDelete.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mKeyboardHelper.handleBackspace();
+ }
+ });
+ }
}
mPasswordEntry.requestFocus();
@@ -293,7 +305,7 @@
mPasswordEntry.setEnabled(false);
mKeyboardView.setEnabled(false);
long elapsedRealtime = SystemClock.elapsedRealtime();
- mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
+ new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
@Override
public void onTick(long millisUntilFinished) {
@@ -309,7 +321,6 @@
mPasswordEntry.setEnabled(true);
mKeyboardView.setEnabled(true);
mStatusViewManager.resetStatusInfo();
- mCountdownTimer = null;
}
}.start();
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index fe49cd2..7b8657a 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -325,14 +325,16 @@
public boolean includeApks;
public boolean includeShared;
public boolean allApps;
+ public boolean includeSystem;
public String[] packages;
FullBackupParams(ParcelFileDescriptor output, boolean saveApks, boolean saveShared,
- boolean doAllApps, String[] pkgList) {
+ boolean doAllApps, boolean doSystem, String[] pkgList) {
fd = output;
includeApks = saveApks;
includeShared = saveShared;
allApps = doAllApps;
+ includeSystem = doSystem;
packages = pkgList;
}
}
@@ -504,7 +506,7 @@
PerformFullBackupTask task = new PerformFullBackupTask(params.fd,
params.observer, params.includeApks,
params.includeShared, params.curPassword, params.encryptPassword,
- params.allApps, params.packages, params.latch);
+ params.allApps, params.includeSystem, params.packages, params.latch);
(new Thread(task)).start();
break;
}
@@ -2161,6 +2163,7 @@
boolean mIncludeApks;
boolean mIncludeShared;
boolean mAllApps;
+ final boolean mIncludeSystem;
String[] mPackages;
String mCurrentPassword;
String mEncryptPassword;
@@ -2219,13 +2222,14 @@
PerformFullBackupTask(ParcelFileDescriptor fd, IFullBackupRestoreObserver observer,
boolean includeApks, boolean includeShared, String curPassword,
- String encryptPassword, boolean doAllApps, String[] packages,
+ String encryptPassword, boolean doAllApps, boolean doSystem, String[] packages,
AtomicBoolean latch) {
mOutputFile = fd;
mObserver = observer;
mIncludeApks = includeApks;
mIncludeShared = includeShared;
mAllApps = doAllApps;
+ mIncludeSystem = doSystem;
mPackages = packages;
mCurrentPassword = curPassword;
// when backing up, if there is a current backup password, we require that
@@ -2245,7 +2249,7 @@
@Override
public void run() {
- final List<PackageInfo> packagesToBackup;
+ List<PackageInfo> packagesToBackup = new ArrayList<PackageInfo>();
Slog.i(TAG, "--- Performing full-dataset backup ---");
sendStartBackup();
@@ -2254,8 +2258,23 @@
if (mAllApps) {
packagesToBackup = mPackageManager.getInstalledPackages(
PackageManager.GET_SIGNATURES);
- } else {
- packagesToBackup = new ArrayList<PackageInfo>();
+ // Exclude system apps if we've been asked to do so
+ if (mIncludeSystem == false) {
+ for (int i = 0; i < packagesToBackup.size(); ) {
+ PackageInfo pkg = packagesToBackup.get(i);
+ if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ packagesToBackup.remove(i);
+ } else {
+ i++;
+ }
+ }
+ }
+ }
+
+ // Now process the command line argument packages, if any. Note that explicitly-
+ // named system-partition packages will be included even if includeSystem was
+ // set to false.
+ if (mPackages != null) {
for (String pkgName : mPackages) {
try {
packagesToBackup.add(mPackageManager.getPackageInfo(pkgName,
@@ -2268,8 +2287,8 @@
// Cull any packages that have indicated that backups are not permitted.
for (int i = 0; i < packagesToBackup.size(); ) {
- PackageInfo info = packagesToBackup.get(i);
- if ((info.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) {
+ PackageInfo pkg = packagesToBackup.get(i);
+ if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) {
packagesToBackup.remove(i);
} else {
i++;
@@ -4781,7 +4800,7 @@
// to the supplied file descriptor. This method is synchronous and does not return
// to the caller until the backup has been completed.
public void fullBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeShared,
- boolean doAllApps, String[] pkgList) {
+ boolean doAllApps, boolean includeSystem, String[] pkgList) {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullBackup");
// Validate
@@ -4811,7 +4830,7 @@
Slog.i(TAG, "Beginning full backup...");
FullBackupParams params = new FullBackupParams(fd, includeApks, includeShared,
- doAllApps, pkgList);
+ doAllApps, includeSystem, pkgList);
final int token = generateToken();
synchronized (mFullConfirmations) {
mFullConfirmations.put(token, params);
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 99f6b8e..a7eff93 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -142,5 +142,5 @@
# ---------------------------
# NetworkStatsService.java
# ---------------------------
-51100 netstats_mobile_sample (iface_rx_bytes|2|2),(iface_tx_bytes|2|2),(iface_rx_pkts|2|1),(iface_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1)
-51101 netstats_wifi_sample (iface_rx_bytes|2|2),(iface_tx_bytes|2|2),(iface_rx_pkts|2|1),(iface_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1)
+51100 netstats_mobile_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3)
+51101 netstats_wifi_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3)
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index aacaa6a..f1a404a 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -22,6 +22,7 @@
import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
+import static android.net.TrafficStats.UID_TETHERING;
import static android.provider.Settings.Secure.NETSTATS_ENABLED;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
@@ -85,11 +86,15 @@
@Deprecated
private final File mStatsUid;
/** Path to {@code /proc/net/dev}. */
+ @Deprecated
private final File mStatsIface;
+ /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */
+ @Deprecated
+ private final File mStatsXtIface;
+ /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
+ private final File mStatsXtIfaceAll;
/** Path to {@code /proc/net/xt_qtaguid/stats}. */
private final File mStatsXtUid;
- /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */
- private final File mStatsXtIface;
/**
* Name representing {@link #setGlobalAlert(long)} limit when delivered to
@@ -97,12 +102,17 @@
*/
public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
- /** {@link #mStatsXtUid} headers. */
+ /** {@link #mStatsXtUid} and {@link #mStatsXtIfaceAll} headers. */
private static final String KEY_IDX = "idx";
private static final String KEY_IFACE = "iface";
+ private static final String KEY_ACTIVE = "active";
private static final String KEY_UID = "uid_tag_int";
private static final String KEY_COUNTER_SET = "cnt_set";
private static final String KEY_TAG_HEX = "acct_tag_hex";
+ private static final String KEY_SNAP_RX_BYTES = "snap_rx_bytes";
+ private static final String KEY_SNAP_RX_PACKETS = "snap_rx_packets";
+ private static final String KEY_SNAP_TX_BYTES = "snap_tx_bytes";
+ private static final String KEY_SNAP_TX_PACKETS = "snap_tx_packets";
private static final String KEY_RX_BYTES = "rx_bytes";
private static final String KEY_RX_PACKETS = "rx_packets";
private static final String KEY_TX_BYTES = "tx_bytes";
@@ -169,6 +179,7 @@
mStatsIface = new File(procRoot, "net/dev");
mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
mStatsXtIface = new File(procRoot, "net/xt_qtaguid/iface_stat");
+ mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
return;
@@ -1071,6 +1082,15 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
+ if (mBandwidthControlEnabled && mStatsXtIfaceAll.exists()) {
+ return getNetworkStatsSummarySingleFile();
+ } else {
+ return getNetworkStatsSummaryMultipleFiles();
+ }
+ }
+
+ @Deprecated
+ private NetworkStats getNetworkStatsSummaryMultipleFiles() {
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
final NetworkStats.Entry entry = new NetworkStats.Entry();
@@ -1155,6 +1175,61 @@
return stats;
}
+ private NetworkStats getNetworkStatsSummarySingleFile() {
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+
+ // TODO: read directly from proc once headers are added
+ final ArrayList<String> keys = Lists.newArrayList(KEY_IFACE, KEY_ACTIVE, KEY_SNAP_RX_BYTES,
+ KEY_SNAP_RX_PACKETS, KEY_SNAP_TX_BYTES, KEY_SNAP_TX_PACKETS, KEY_RX_BYTES,
+ KEY_RX_PACKETS, KEY_TX_BYTES, KEY_TX_PACKETS);
+ final ArrayList<String> values = Lists.newArrayList();
+ final HashMap<String, String> parsed = Maps.newHashMap();
+
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(mStatsXtIfaceAll));
+
+ String line;
+ while ((line = reader.readLine()) != null) {
+ splitLine(line, values);
+ parseLine(keys, values, parsed);
+
+ entry.iface = parsed.get(KEY_IFACE);
+ entry.uid = UID_ALL;
+ entry.set = SET_DEFAULT;
+ entry.tag = TAG_NONE;
+
+ // always include snapshot values
+ entry.rxBytes = getParsedLong(parsed, KEY_SNAP_RX_BYTES);
+ entry.rxPackets = getParsedLong(parsed, KEY_SNAP_RX_PACKETS);
+ entry.txBytes = getParsedLong(parsed, KEY_SNAP_TX_BYTES);
+ entry.txPackets = getParsedLong(parsed, KEY_SNAP_TX_PACKETS);
+
+ // fold in active numbers, but only when active
+ final boolean active = getParsedInt(parsed, KEY_ACTIVE) != 0;
+ if (active) {
+ entry.rxBytes += getParsedLong(parsed, KEY_RX_BYTES);
+ entry.rxPackets += getParsedLong(parsed, KEY_RX_PACKETS);
+ entry.txBytes += getParsedLong(parsed, KEY_TX_BYTES);
+ entry.txPackets += getParsedLong(parsed, KEY_TX_PACKETS);
+ }
+
+ stats.addValues(entry);
+ }
+ } catch (NullPointerException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
+ } catch (IOException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
+ } finally {
+ IoUtils.closeQuietly(reader);
+ }
+
+ return stats;
+ }
+
@Override
public NetworkStats getNetworkStatsDetail() {
mContext.enforceCallingOrSelfPermission(
@@ -1522,7 +1597,7 @@
try {
final NetworkStats.Entry entry = new NetworkStats.Entry();
entry.iface = ifaceIn;
- entry.uid = UID_ALL;
+ entry.uid = UID_TETHERING;
entry.set = SET_DEFAULT;
entry.tag = TAG_NONE;
entry.rxBytes = Long.parseLong(tok[3]);
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index aa46795..e5f0a77 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -35,7 +35,6 @@
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.UID_REMOVED;
-import static android.net.TrafficStats.UID_TETHERING;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD;
@@ -72,7 +71,6 @@
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
-import android.net.TrafficStats;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
@@ -140,11 +138,14 @@
private static final int MSG_UPDATE_IFACES = 2;
/** Flags to control detail level of poll event. */
- private static final int FLAG_PERSIST_NETWORK = 0x10;
- private static final int FLAG_PERSIST_UID = 0x20;
+ private static final int FLAG_PERSIST_NETWORK = 0x1;
+ private static final int FLAG_PERSIST_UID = 0x2;
private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
private static final int FLAG_PERSIST_FORCE = 0x100;
+ /** Sample recent usage after each poll event. */
+ private static final boolean ENABLE_SAMPLE_AFTER_POLL = true;
+
private final Context mContext;
private final INetworkManagementService mNetworkManager;
private final IAlarmManager mAlarmManager;
@@ -188,20 +189,23 @@
/** Set of currently active ifaces. */
private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
- /** Set of historical network layer stats for known networks. */
- private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkStats = Maps.newHashMap();
- /** Set of historical network layer stats for known UIDs. */
+ /** Set of historical {@code dev} stats for known networks. */
+ private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkDevStats = Maps.newHashMap();
+ /** Set of historical {@code xtables} stats for known networks. */
+ private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkXtStats = Maps.newHashMap();
+ /** Set of historical {@code xtables} stats for known UIDs. */
private HashMap<UidStatsKey, NetworkStatsHistory> mUidStats = Maps.newHashMap();
/** Flag if {@link #mUidStats} have been loaded from disk. */
private boolean mUidStatsLoaded = false;
- private NetworkStats mLastPollNetworkSnapshot;
+ private NetworkStats mLastPollNetworkDevSnapshot;
+ private NetworkStats mLastPollNetworkXtSnapshot;
private NetworkStats mLastPollUidSnapshot;
private NetworkStats mLastPollOperationsSnapshot;
- private NetworkStats mLastPollTetherSnapshot;
- private NetworkStats mLastPersistNetworkSnapshot;
+ private NetworkStats mLastPersistNetworkDevSnapshot;
+ private NetworkStats mLastPersistNetworkXtSnapshot;
private NetworkStats mLastPersistUidSnapshot;
/** Current counter sets for each UID. */
@@ -213,7 +217,8 @@
private final HandlerThread mHandlerThread;
private final Handler mHandler;
- private final AtomicFile mNetworkFile;
+ private final AtomicFile mNetworkDevFile;
+ private final AtomicFile mNetworkXtFile;
private final AtomicFile mUidFile;
public NetworkStatsService(
@@ -244,7 +249,8 @@
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
- mNetworkFile = new AtomicFile(new File(systemDir, "netstats.bin"));
+ mNetworkDevFile = new AtomicFile(new File(systemDir, "netstats.bin"));
+ mNetworkXtFile = new AtomicFile(new File(systemDir, "netstats_xt.bin"));
mUidFile = new AtomicFile(new File(systemDir, "netstats_uid.bin"));
}
@@ -257,7 +263,8 @@
// read historical network stats from disk, since policy service
// might need them right away. we delay loading detailed UID stats
// until actually needed.
- readNetworkStatsLocked();
+ readNetworkDevStatsLocked();
+ readNetworkXtStatsLocked();
}
// watch for network interfaces to be claimed
@@ -306,11 +313,13 @@
mTeleManager.listen(mPhoneListener, LISTEN_NONE);
- writeNetworkStatsLocked();
+ writeNetworkDevStatsLocked();
+ writeNetworkXtStatsLocked();
if (mUidStatsLoaded) {
writeUidStatsLocked();
}
- mNetworkStats.clear();
+ mNetworkDevStats.clear();
+ mNetworkXtStats.clear();
mUidStats.clear();
mUidStatsLoaded = false;
}
@@ -355,14 +364,26 @@
@Override
public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+ return getHistoryForNetworkDev(template, fields);
+ }
+ private NetworkStatsHistory getHistoryForNetworkDev(NetworkTemplate template, int fields) {
+ return getHistoryForNetwork(template, fields, mNetworkDevStats);
+ }
+
+ private NetworkStatsHistory getHistoryForNetworkXt(NetworkTemplate template, int fields) {
+ return getHistoryForNetwork(template, fields, mNetworkXtStats);
+ }
+
+ private NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields,
+ HashMap<NetworkIdentitySet, NetworkStatsHistory> source) {
synchronized (mStatsLock) {
// combine all interfaces that match template
final NetworkStatsHistory combined = new NetworkStatsHistory(
mSettings.getNetworkBucketDuration(), estimateNetworkBuckets(), fields);
- for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
+ for (NetworkIdentitySet ident : source.keySet()) {
if (templateMatches(template, ident)) {
- final NetworkStatsHistory history = mNetworkStats.get(ident);
+ final NetworkStatsHistory history = source.get(ident);
if (history != null) {
combined.recordEntireHistory(history);
}
@@ -399,7 +420,19 @@
@Override
public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+ return getSummaryForNetworkDev(template, start, end);
+ }
+ private NetworkStats getSummaryForNetworkDev(NetworkTemplate template, long start, long end) {
+ return getSummaryForNetwork(template, start, end, mNetworkDevStats);
+ }
+
+ private NetworkStats getSummaryForNetworkXt(NetworkTemplate template, long start, long end) {
+ return getSummaryForNetwork(template, start, end, mNetworkXtStats);
+ }
+
+ private NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end,
+ HashMap<NetworkIdentitySet, NetworkStatsHistory> source) {
synchronized (mStatsLock) {
// use system clock to be externally consistent
final long now = System.currentTimeMillis();
@@ -409,9 +442,9 @@
NetworkStatsHistory.Entry historyEntry = null;
// combine total from all interfaces that match template
- for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
+ for (NetworkIdentitySet ident : source.keySet()) {
if (templateMatches(template, ident)) {
- final NetworkStatsHistory history = mNetworkStats.get(ident);
+ final NetworkStatsHistory history = source.get(ident);
historyEntry = history.getValues(start, end, now, historyEntry);
entry.iface = IFACE_ALL;
@@ -716,8 +749,9 @@
*/
private void bootstrapStats() {
try {
- mLastPollNetworkSnapshot = mNetworkManager.getNetworkStatsSummary();
mLastPollUidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
+ mLastPollNetworkDevSnapshot = mNetworkManager.getNetworkStatsSummary();
+ mLastPollNetworkXtSnapshot = computeNetworkXtSnapshotFromUid(mLastPollUidSnapshot);
mLastPollOperationsSnapshot = new NetworkStats(0L, 0);
} catch (IllegalStateException e) {
Slog.w(TAG, "problem reading network stats: " + e);
@@ -759,42 +793,56 @@
: System.currentTimeMillis();
final long threshold = mSettings.getPersistThreshold();
+ final NetworkStats uidSnapshot;
+ final NetworkStats networkXtSnapshot;
+ final NetworkStats networkDevSnapshot;
try {
- // record tethering stats; persisted during normal UID cycle below
- final String[] ifacePairs = mConnManager.getTetheredIfacePairs();
+ // collect any tethering stats
+ final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs();
final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering(
- ifacePairs);
- performTetherPollLocked(tetherSnapshot, currentTime);
+ tetheredIfacePairs);
- // record uid stats
- final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
+ // record uid stats, folding in tethering stats
+ uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
+ uidSnapshot.combineAllValues(tetherSnapshot);
performUidPollLocked(uidSnapshot, currentTime);
- // persist when enough network data has occurred
- final NetworkStats persistUidDelta = computeStatsDelta(
- mLastPersistUidSnapshot, uidSnapshot, true);
- final boolean uidPastThreshold = persistUidDelta.getTotalBytes() > threshold;
- if (persistForce || (persistUid && uidPastThreshold)) {
- writeUidStatsLocked();
- mLastPersistUidSnapshot = uidSnapshot;
- }
+ // record dev network stats
+ networkDevSnapshot = mNetworkManager.getNetworkStatsSummary();
+ performNetworkDevPollLocked(networkDevSnapshot, currentTime);
- // record network stats
- final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary();
- performNetworkPollLocked(networkSnapshot, currentTime);
+ // record xt network stats
+ networkXtSnapshot = computeNetworkXtSnapshotFromUid(uidSnapshot);
+ performNetworkXtPollLocked(networkXtSnapshot, currentTime);
- // persist when enough network data has occurred
- final NetworkStats persistNetworkDelta = computeStatsDelta(
- mLastPersistNetworkSnapshot, networkSnapshot, true);
- final boolean networkPastThreshold = persistNetworkDelta.getTotalBytes() > threshold;
- if (persistForce || (persistNetwork && networkPastThreshold)) {
- writeNetworkStatsLocked();
- mLastPersistNetworkSnapshot = networkSnapshot;
- }
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem reading network stats", e);
+ return;
} catch (RemoteException e) {
// ignored; service lives in system_server
+ return;
+ }
+
+ // persist when enough network data has occurred
+ final long persistNetworkDevDelta = computeStatsDelta(
+ mLastPersistNetworkDevSnapshot, networkDevSnapshot, true).getTotalBytes();
+ final long persistNetworkXtDelta = computeStatsDelta(
+ mLastPersistNetworkXtSnapshot, networkXtSnapshot, true).getTotalBytes();
+ final boolean networkOverThreshold = persistNetworkDevDelta > threshold
+ || persistNetworkXtDelta > threshold;
+ if (persistForce || (persistNetwork && networkOverThreshold)) {
+ writeNetworkDevStatsLocked();
+ writeNetworkXtStatsLocked();
+ mLastPersistNetworkDevSnapshot = networkDevSnapshot;
+ mLastPersistNetworkXtSnapshot = networkXtSnapshot;
+ }
+
+ // persist when enough uid data has occurred
+ final long persistUidDelta = computeStatsDelta(mLastPersistUidSnapshot, uidSnapshot, true)
+ .getTotalBytes();
+ if (persistForce || (persistUid && persistUidDelta > threshold)) {
+ writeUidStatsLocked();
+ mLastPersistUidSnapshot = uidSnapshot;
}
if (LOGV) {
@@ -802,8 +850,10 @@
Slog.v(TAG, "performPollLocked() took " + duration + "ms");
}
- // sample stats after each full poll
- performSample();
+ if (ENABLE_SAMPLE_AFTER_POLL) {
+ // sample stats after each full poll
+ performSample();
+ }
// finally, dispatch updated event to any listeners
final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
@@ -812,12 +862,13 @@
}
/**
- * Update {@link #mNetworkStats} historical usage.
+ * Update {@link #mNetworkDevStats} historical usage.
*/
- private void performNetworkPollLocked(NetworkStats networkSnapshot, long currentTime) {
+ private void performNetworkDevPollLocked(NetworkStats networkDevSnapshot, long currentTime) {
final HashSet<String> unknownIface = Sets.newHashSet();
- final NetworkStats delta = computeStatsDelta(mLastPollNetworkSnapshot, networkSnapshot, false);
+ final NetworkStats delta = computeStatsDelta(
+ mLastPollNetworkDevSnapshot, networkDevSnapshot, false);
final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null;
@@ -829,14 +880,44 @@
continue;
}
- final NetworkStatsHistory history = findOrCreateNetworkStatsLocked(ident);
+ final NetworkStatsHistory history = findOrCreateNetworkDevStatsLocked(ident);
history.recordData(timeStart, currentTime, entry);
}
- mLastPollNetworkSnapshot = networkSnapshot;
+ mLastPollNetworkDevSnapshot = networkDevSnapshot;
if (LOGD && unknownIface.size() > 0) {
- Slog.w(TAG, "unknown interfaces " + unknownIface.toString() + ", ignoring those stats");
+ Slog.w(TAG, "unknown dev interfaces " + unknownIface + ", ignoring those stats");
+ }
+ }
+
+ /**
+ * Update {@link #mNetworkXtStats} historical usage.
+ */
+ private void performNetworkXtPollLocked(NetworkStats networkXtSnapshot, long currentTime) {
+ final HashSet<String> unknownIface = Sets.newHashSet();
+
+ final NetworkStats delta = computeStatsDelta(
+ mLastPollNetworkXtSnapshot, networkXtSnapshot, false);
+ final long timeStart = currentTime - delta.getElapsedRealtime();
+
+ NetworkStats.Entry entry = null;
+ for (int i = 0; i < delta.size(); i++) {
+ entry = delta.getValues(i, entry);
+ final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
+ if (ident == null) {
+ unknownIface.add(entry.iface);
+ continue;
+ }
+
+ final NetworkStatsHistory history = findOrCreateNetworkXtStatsLocked(ident);
+ history.recordData(timeStart, currentTime, entry);
+ }
+
+ mLastPollNetworkXtSnapshot = networkXtSnapshot;
+
+ if (LOGD && unknownIface.size() > 0) {
+ Slog.w(TAG, "unknown xt interfaces " + unknownIface + ", ignoring those stats");
}
}
@@ -882,38 +963,6 @@
}
/**
- * Update {@link #mUidStats} historical usage for
- * {@link TrafficStats#UID_TETHERING} based on tethering statistics.
- */
- private void performTetherPollLocked(NetworkStats tetherSnapshot, long currentTime) {
- ensureUidStatsLoadedLocked();
-
- final NetworkStats delta = computeStatsDelta(
- mLastPollTetherSnapshot, tetherSnapshot, false);
- final long timeStart = currentTime - delta.getElapsedRealtime();
-
- NetworkStats.Entry entry = null;
- for (int i = 0; i < delta.size(); i++) {
- entry = delta.getValues(i, entry);
- final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
- if (ident == null) {
- if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0
- || entry.txPackets > 0) {
- Log.w(TAG, "dropping tether delta from unknown iface: " + entry);
- }
- continue;
- }
-
- final NetworkStatsHistory history = findOrCreateUidStatsLocked(
- ident, UID_TETHERING, SET_DEFAULT, TAG_NONE);
- history.recordData(timeStart, currentTime, entry);
- }
-
- // normal UID poll will trim any history beyond max
- mLastPollTetherSnapshot = tetherSnapshot;
- }
-
- /**
* Sample recent statistics summary into {@link EventLog}.
*/
private void performSample() {
@@ -925,25 +974,34 @@
final long end = now - (now % largestBucketSize) + largestBucketSize;
final long start = end - largestBucketSize;
+ final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
+
NetworkTemplate template = null;
- NetworkStats.Entry ifaceTotal = null;
+ NetworkStats.Entry devTotal = null;
+ NetworkStats.Entry xtTotal = null;
NetworkStats.Entry uidTotal = null;
// collect mobile sample
template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
- ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal);
+ devTotal = getSummaryForNetworkDev(template, start, end).getTotal(devTotal);
+ xtTotal = getSummaryForNetworkXt(template, start, end).getTotal(xtTotal);
uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
- EventLogTags.writeNetstatsMobileSample(ifaceTotal.rxBytes, ifaceTotal.rxPackets,
- ifaceTotal.txBytes, ifaceTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets,
- uidTotal.txBytes, uidTotal.txPackets);
+ EventLogTags.writeNetstatsMobileSample(
+ devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
+ xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
+ uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
+ trustedTime);
// collect wifi sample
template = buildTemplateWifi();
- ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal);
+ devTotal = getSummaryForNetworkDev(template, start, end).getTotal(devTotal);
+ xtTotal = getSummaryForNetworkXt(template, start, end).getTotal(xtTotal);
uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
- EventLogTags.writeNetstatsWifiSample(ifaceTotal.rxBytes, ifaceTotal.rxPackets,
- ifaceTotal.txBytes, ifaceTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets,
- uidTotal.txBytes, uidTotal.txPackets);
+ EventLogTags.writeNetstatsWifiSample(
+ devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
+ xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
+ uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
+ trustedTime);
}
/**
@@ -976,8 +1034,17 @@
writeUidStatsLocked();
}
- private NetworkStatsHistory findOrCreateNetworkStatsLocked(NetworkIdentitySet ident) {
- final NetworkStatsHistory existing = mNetworkStats.get(ident);
+ private NetworkStatsHistory findOrCreateNetworkXtStatsLocked(NetworkIdentitySet ident) {
+ return findOrCreateNetworkStatsLocked(ident, mNetworkXtStats);
+ }
+
+ private NetworkStatsHistory findOrCreateNetworkDevStatsLocked(NetworkIdentitySet ident) {
+ return findOrCreateNetworkStatsLocked(ident, mNetworkDevStats);
+ }
+
+ private NetworkStatsHistory findOrCreateNetworkStatsLocked(
+ NetworkIdentitySet ident, HashMap<NetworkIdentitySet, NetworkStatsHistory> source) {
+ final NetworkStatsHistory existing = source.get(ident);
// update when no existing, or when bucket duration changed
final long bucketDuration = mSettings.getNetworkBucketDuration();
@@ -991,7 +1058,7 @@
}
if (updated != null) {
- mNetworkStats.put(ident, updated);
+ source.put(ident, updated);
return updated;
} else {
return existing;
@@ -1024,15 +1091,24 @@
}
}
- private void readNetworkStatsLocked() {
- if (LOGV) Slog.v(TAG, "readNetworkStatsLocked()");
+ private void readNetworkDevStatsLocked() {
+ if (LOGV) Slog.v(TAG, "readNetworkDevStatsLocked()");
+ readNetworkStats(mNetworkDevFile, mNetworkDevStats);
+ }
+ private void readNetworkXtStatsLocked() {
+ if (LOGV) Slog.v(TAG, "readNetworkXtStatsLocked()");
+ readNetworkStats(mNetworkXtFile, mNetworkXtStats);
+ }
+
+ private static void readNetworkStats(
+ AtomicFile inputFile, HashMap<NetworkIdentitySet, NetworkStatsHistory> output) {
// clear any existing stats and read from disk
- mNetworkStats.clear();
+ output.clear();
DataInputStream in = null;
try {
- in = new DataInputStream(new BufferedInputStream(mNetworkFile.openRead()));
+ in = new DataInputStream(new BufferedInputStream(inputFile.openRead()));
// verify file magic header intact
final int magic = in.readInt();
@@ -1048,7 +1124,7 @@
for (int i = 0; i < size; i++) {
final NetworkIdentitySet ident = new NetworkIdentitySet(in);
final NetworkStatsHistory history = new NetworkStatsHistory(in);
- mNetworkStats.put(ident, history);
+ output.put(ident, history);
}
break;
}
@@ -1138,41 +1214,50 @@
}
}
- private void writeNetworkStatsLocked() {
- if (LOGV) Slog.v(TAG, "writeNetworkStatsLocked()");
+ private void writeNetworkDevStatsLocked() {
+ if (LOGV) Slog.v(TAG, "writeNetworkDevStatsLocked()");
+ writeNetworkStats(mNetworkDevStats, mNetworkDevFile);
+ }
+ private void writeNetworkXtStatsLocked() {
+ if (LOGV) Slog.v(TAG, "writeNetworkXtStatsLocked()");
+ writeNetworkStats(mNetworkXtStats, mNetworkXtFile);
+ }
+
+ private void writeNetworkStats(
+ HashMap<NetworkIdentitySet, NetworkStatsHistory> input, AtomicFile outputFile) {
// TODO: consider duplicating stats and releasing lock while writing
// trim any history beyond max
if (mTime.hasCache()) {
final long currentTime = mTime.currentTimeMillis();
final long maxHistory = mSettings.getNetworkMaxHistory();
- for (NetworkStatsHistory history : mNetworkStats.values()) {
+ for (NetworkStatsHistory history : input.values()) {
history.removeBucketsBefore(currentTime - maxHistory);
}
}
FileOutputStream fos = null;
try {
- fos = mNetworkFile.startWrite();
+ fos = outputFile.startWrite();
final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
out.writeInt(FILE_MAGIC);
out.writeInt(VERSION_NETWORK_INIT);
- out.writeInt(mNetworkStats.size());
- for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
- final NetworkStatsHistory history = mNetworkStats.get(ident);
+ out.writeInt(input.size());
+ for (NetworkIdentitySet ident : input.keySet()) {
+ final NetworkStatsHistory history = input.get(ident);
ident.writeToStream(out);
history.writeToStream(out);
}
out.flush();
- mNetworkFile.finishWrite(fos);
+ outputFile.finishWrite(fos);
} catch (IOException e) {
Log.wtf(TAG, "problem writing stats", e);
if (fos != null) {
- mNetworkFile.failWrite(fos);
+ outputFile.failWrite(fos);
}
}
}
@@ -1280,9 +1365,16 @@
pw.print(" ident="); pw.println(ident.toString());
}
- pw.println("Known historical stats:");
- for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
- final NetworkStatsHistory history = mNetworkStats.get(ident);
+ pw.println("Known historical dev stats:");
+ for (NetworkIdentitySet ident : mNetworkDevStats.keySet()) {
+ final NetworkStatsHistory history = mNetworkDevStats.get(ident);
+ pw.print(" ident="); pw.println(ident.toString());
+ history.dump(" ", pw, fullHistory);
+ }
+
+ pw.println("Known historical xt stats:");
+ for (NetworkIdentitySet ident : mNetworkXtStats.keySet()) {
+ final NetworkStatsHistory history = mNetworkXtStats.get(ident);
pw.print(" ident="); pw.println(ident.toString());
history.dump(" ", pw, fullHistory);
}
@@ -1333,10 +1425,13 @@
final List<ApplicationInfo> installedApps = mContext
.getPackageManager().getInstalledApplications(0);
- mNetworkStats.clear();
+ mNetworkDevStats.clear();
+ mNetworkXtStats.clear();
mUidStats.clear();
for (NetworkIdentitySet ident : mActiveIfaces.values()) {
- findOrCreateNetworkStatsLocked(ident).generateRandom(NET_START, NET_END, NET_RX_BYTES,
+ findOrCreateNetworkDevStatsLocked(ident).generateRandom(NET_START, NET_END,
+ NET_RX_BYTES, NET_RX_PACKETS, NET_TX_BYTES, NET_TX_PACKETS, 0L);
+ findOrCreateNetworkXtStatsLocked(ident).generateRandom(NET_START, NET_END, NET_RX_BYTES,
NET_RX_PACKETS, NET_TX_BYTES, NET_TX_PACKETS, 0L);
for (ApplicationInfo info : installedApps) {
@@ -1369,6 +1464,10 @@
}
}
+ private static NetworkStats computeNetworkXtSnapshotFromUid(NetworkStats uidSnapshot) {
+ return uidSnapshot.groupedByIface();
+ }
+
private int estimateNetworkBuckets() {
return (int) (mSettings.getNetworkMaxHistory() / mSettings.getNetworkBucketDuration());
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index eb135b7..19dd606 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -753,7 +753,7 @@
if (state != null) {
final InstallArgs args = state.getInstallArgs();
- Slog.i(TAG, "Validation timed out for " + args.packageURI.toString());
+ Slog.i(TAG, "Verification timed out for " + args.packageURI.toString());
mPendingVerification.remove(verificationId);
int ret = PackageManager.INSTALL_FAILED_VERIFICATION_TIMEOUT;
@@ -769,7 +769,7 @@
final PackageVerificationState state = mPendingVerification.get(verificationId);
if (state == null) {
- Slog.w(TAG, "Invalid validation token " + verificationId + " received");
+ Slog.w(TAG, "Invalid verification token " + verificationId + " received");
break;
}
@@ -5464,8 +5464,8 @@
final int requiredUid = mRequiredVerifierPackage == null ? -1
: getPackageUid(mRequiredVerifierPackage);
if (requiredUid != -1 && isVerificationEnabled()) {
- final Intent verification = new Intent(
- Intent.ACTION_PACKAGE_NEEDS_VERIFICATION, packageURI);
+ final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+ verification.setDataAndType(packageURI, PACKAGE_MIME_TYPE);
verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
diff --git a/services/tests/servicestests/res/raw/xt_qtaguid_iface_typical b/services/tests/servicestests/res/raw/xt_qtaguid_iface_typical
new file mode 100644
index 0000000..efa4cd5
--- /dev/null
+++ b/services/tests/servicestests/res/raw/xt_qtaguid_iface_typical
@@ -0,0 +1,6 @@
+rmnet3 1 0 0 0 0 20822 501 1149991 815
+rmnet2 1 0 0 0 0 1594 15 1313 15
+rmnet1 1 0 0 0 0 207398 458 166918 565
+rmnet0 1 0 0 0 0 2112 24 700 10
+test1 1 1 2 3 4 5 6 7 8
+test2 0 1 2 3 4 5 6 7 8
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
index ab1597c..40640e0 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
@@ -159,6 +159,16 @@
assertStatsEntry(stats, "rmnet0", 1000, SET_FOREGROUND, 0, 26033L, 30L, 1401L, 26L);
}
+ public void testNetworkStatsSingle() throws Exception {
+ stageFile(R.raw.xt_qtaguid_iface_typical, new File(mTestProc, "net/xt_qtaguid/iface_stat_all"));
+
+ final NetworkStats stats = mService.getNetworkStatsSummary();
+ assertEquals(6, stats.size());
+ assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 2112L, 24L, 700L, 10L);
+ assertStatsEntry(stats, "test1", UID_ALL, SET_DEFAULT, TAG_NONE, 6L, 8L, 10L, 12L);
+ assertStatsEntry(stats, "test2", UID_ALL, SET_DEFAULT, TAG_NONE, 1L, 2L, 3L, 4L);
+ }
+
/**
* Copy a {@link Resources#openRawResource(int)} into {@link File} for
* testing purposes.
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 2ead254..f7dff23 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -32,6 +32,7 @@
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.UID_REMOVED;
+import static android.net.TrafficStats.UID_TETHERING;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@@ -179,6 +180,7 @@
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -232,6 +234,7 @@
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -327,6 +330,7 @@
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -378,6 +382,7 @@
expectNetworkState(buildMobile3gState(IMSI_1));
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -459,6 +464,7 @@
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -518,6 +524,7 @@
expectNetworkState(buildMobile3gState(IMSI_1));
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -585,6 +592,7 @@
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -648,6 +656,7 @@
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -705,6 +714,42 @@
verifyAndReset();
}
+ public void testTethering() throws Exception {
+ // pretend first mobile network comes online
+ expectCurrentTime();
+ expectDefaultSettings();
+ expectNetworkState(buildMobile3gState(IMSI_1));
+ expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
+ verifyAndReset();
+
+ // create some tethering traffic
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectCurrentTime();
+ expectDefaultSettings();
+ expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
+ .addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L));
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
+ .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L));
+ final String[] tetherIfacePairs = new String[] { TEST_IFACE, "wlan0" };
+ expectNetworkStatsPoll(tetherIfacePairs, new NetworkStats(getElapsedRealtime(), 1)
+ .addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L, 0L));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
+
+ // verify service recorded history
+ assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0);
+ assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 0);
+ assertUidTotal(sTemplateImsi1, UID_TETHERING, 1920L, 14L, 384L, 2L, 0);
+ verifyAndReset();
+
+ }
+
private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long rxPackets,
long txBytes, long txPackets, int operations) {
final NetworkStatsHistory history = mService.getHistoryForNetwork(template, FIELD_ALL);
@@ -774,9 +819,16 @@
}
private void expectNetworkStatsPoll() throws Exception {
+ expectNetworkStatsPoll(new String[0], new NetworkStats(getElapsedRealtime(), 0));
+ }
+
+ private void expectNetworkStatsPoll(String[] tetherIfacePairs, NetworkStats tetherStats)
+ throws Exception {
mNetManager.setGlobalAlert(anyLong());
expectLastCall().anyTimes();
- expect(mConnManager.getTetheredIfacePairs()).andReturn(null).anyTimes();
+ expect(mConnManager.getTetheredIfacePairs()).andReturn(tetherIfacePairs).anyTimes();
+ expect(mNetManager.getNetworkStatsTethering(eq(tetherIfacePairs)))
+ .andReturn(tetherStats).anyTimes();
}
private void assertStatsFilesExist(boolean exist) {
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 18d6eaa..568a485 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -100,6 +100,7 @@
private static Context sContext;
private static final String TAG = "WifiConfigStore";
+ private static final boolean DBG = false;
/* configured networks with network id as the key */
private static HashMap<Integer, WifiConfiguration> sConfiguredNetworks =
@@ -140,7 +141,7 @@
* and enable all stored networks in supplicant.
*/
static void initialize(Context context) {
- Log.d(TAG, "Loading config and enabling all networks");
+ if (DBG) log("Loading config and enabling all networks");
sContext = context;
loadConfiguredNetworks();
enableAllNetworks();
@@ -173,7 +174,7 @@
networkEnabledStateChanged = true;
config.status = Status.ENABLED;
} else {
- Log.e(TAG, "Enable network failed on " + config.networkId);
+ loge("Enable network failed on " + config.networkId);
}
}
}
@@ -204,7 +205,7 @@
if (netId != INVALID_NETWORK_ID) {
selectNetwork(netId);
} else {
- Log.e(TAG, "Failed to update network " + config);
+ loge("Failed to update network " + config);
}
return netId;
}
@@ -290,7 +291,7 @@
writeIpAndProxyConfigurations();
sendConfiguredNetworksChangedBroadcast();
} else {
- Log.e(TAG, "Failed to remove network " + netId);
+ loge("Failed to remove network " + netId);
}
}
@@ -404,7 +405,7 @@
markAllNetworksDisabled();
result.status = WpsResult.Status.SUCCESS;
} else {
- Log.e(TAG, "Failed to start WPS pin method configuration");
+ loge("Failed to start WPS pin method configuration");
result.status = WpsResult.Status.FAILURE;
}
return result;
@@ -423,7 +424,7 @@
markAllNetworksDisabled();
result.status = WpsResult.Status.SUCCESS;
} else {
- Log.e(TAG, "Failed to start WPS pin method configuration");
+ loge("Failed to start WPS pin method configuration");
result.status = WpsResult.Status.FAILURE;
}
return result;
@@ -439,7 +440,7 @@
markAllNetworksDisabled();
result.status = WpsResult.Status.SUCCESS;
} else {
- Log.e(TAG, "Failed to start WPS push button configuration");
+ loge("Failed to start WPS push button configuration");
result.status = WpsResult.Status.FAILURE;
}
return result;
@@ -680,7 +681,7 @@
/* Ignore */
break;
default:
- Log.e(TAG, "Ignore invalid ip assignment while writing");
+ loge("Ignore invalid ip assignment while writing");
break;
}
@@ -707,7 +708,7 @@
/* Ignore */
break;
default:
- Log.e(TAG, "Ignore invalid proxy settings while writing");
+ loge("Ignore invalid proxy settings while writing");
break;
}
if (writeToFile) {
@@ -715,14 +716,14 @@
out.writeInt(configKey(config));
}
} catch (NullPointerException e) {
- Log.e(TAG, "Failure in writing " + config.linkProperties + e);
+ loge("Failure in writing " + config.linkProperties + e);
}
out.writeUTF(EOS);
}
}
} catch (IOException e) {
- Log.e(TAG, "Error writing data file");
+ loge("Error writing data file");
} finally {
if (out != null) {
try {
@@ -741,7 +742,7 @@
int version = in.readInt();
if (version != 2 && version != 1) {
- Log.e(TAG, "Bad version on IP configuration file, ignore read");
+ loge("Bad version on IP configuration file, ignore read");
return;
}
@@ -797,10 +798,10 @@
} else if (key.equals(EOS)) {
break;
} else {
- Log.e(TAG, "Ignore unknown key " + key + "while reading");
+ loge("Ignore unknown key " + key + "while reading");
}
} catch (IllegalArgumentException e) {
- Log.e(TAG, "Ignore invalid address while reading" + e);
+ loge("Ignore invalid address while reading" + e);
}
} while (true);
@@ -810,7 +811,7 @@
sNetworkIds.get(id));
if (config == null) {
- Log.e(TAG, "configuration found for missing network, ignored");
+ loge("configuration found for missing network, ignored");
} else {
config.linkProperties = linkProperties;
switch (ipAssignment) {
@@ -822,7 +823,7 @@
//Ignore
break;
default:
- Log.e(TAG, "Ignore invalid ip assignment while reading");
+ loge("Ignore invalid ip assignment while reading");
break;
}
@@ -840,18 +841,18 @@
//Ignore
break;
default:
- Log.e(TAG, "Ignore invalid proxy settings while reading");
+ loge("Ignore invalid proxy settings while reading");
break;
}
}
}
} else {
- Log.e(TAG, "Missing id while parsing configuration");
+ loge("Missing id while parsing configuration");
}
}
} catch (EOFException ignore) {
} catch (IOException e) {
- Log.e(TAG, "Error parsing configuration" + e);
+ loge("Error parsing configuration" + e);
} finally {
if (in != null) {
try {
@@ -878,7 +879,7 @@
newNetwork = true;
netId = WifiNative.addNetworkCommand();
if (netId < 0) {
- Log.e(TAG, "Failed to add a network!");
+ loge("Failed to add a network!");
return new NetworkUpdateResult(INVALID_NETWORK_ID);
}
}
@@ -893,7 +894,7 @@
netId,
WifiConfiguration.ssidVarName,
config.SSID)) {
- Log.d(TAG, "failed to set SSID: "+config.SSID);
+ loge("failed to set SSID: "+config.SSID);
break setVariables;
}
@@ -902,7 +903,7 @@
netId,
WifiConfiguration.bssidVarName,
config.BSSID)) {
- Log.d(TAG, "failed to set BSSID: "+config.BSSID);
+ loge("failed to set BSSID: "+config.BSSID);
break setVariables;
}
@@ -913,7 +914,7 @@
netId,
WifiConfiguration.KeyMgmt.varName,
allowedKeyManagementString)) {
- Log.d(TAG, "failed to set key_mgmt: "+
+ loge("failed to set key_mgmt: "+
allowedKeyManagementString);
break setVariables;
}
@@ -925,7 +926,7 @@
netId,
WifiConfiguration.Protocol.varName,
allowedProtocolsString)) {
- Log.d(TAG, "failed to set proto: "+
+ loge("failed to set proto: "+
allowedProtocolsString);
break setVariables;
}
@@ -937,7 +938,7 @@
netId,
WifiConfiguration.AuthAlgorithm.varName,
allowedAuthAlgorithmsString)) {
- Log.d(TAG, "failed to set auth_alg: "+
+ loge("failed to set auth_alg: "+
allowedAuthAlgorithmsString);
break setVariables;
}
@@ -950,7 +951,7 @@
netId,
WifiConfiguration.PairwiseCipher.varName,
allowedPairwiseCiphersString)) {
- Log.d(TAG, "failed to set pairwise: "+
+ loge("failed to set pairwise: "+
allowedPairwiseCiphersString);
break setVariables;
}
@@ -962,7 +963,7 @@
netId,
WifiConfiguration.GroupCipher.varName,
allowedGroupCiphersString)) {
- Log.d(TAG, "failed to set group: "+
+ loge("failed to set group: "+
allowedGroupCiphersString);
break setVariables;
}
@@ -974,7 +975,7 @@
netId,
WifiConfiguration.pskVarName,
config.preSharedKey)) {
- Log.d(TAG, "failed to set psk");
+ loge("failed to set psk");
break setVariables;
}
@@ -988,9 +989,7 @@
netId,
WifiConfiguration.wepKeyVarNames[i],
config.wepKeys[i])) {
- Log.d(TAG,
- "failed to set wep_key"+i+": " +
- config.wepKeys[i]);
+ loge("failed to set wep_key" + i + ": " + config.wepKeys[i]);
break setVariables;
}
hasSetKey = true;
@@ -1003,9 +1002,7 @@
netId,
WifiConfiguration.wepTxKeyIdxVarName,
Integer.toString(config.wepTxKeyIndex))) {
- Log.d(TAG,
- "failed to set wep_tx_keyidx: "+
- config.wepTxKeyIndex);
+ loge("failed to set wep_tx_keyidx: " + config.wepTxKeyIndex);
break setVariables;
}
}
@@ -1014,7 +1011,7 @@
netId,
WifiConfiguration.priorityVarName,
Integer.toString(config.priority))) {
- Log.d(TAG, config.SSID + ": failed to set priority: "
+ loge(config.SSID + ": failed to set priority: "
+config.priority);
break setVariables;
}
@@ -1023,7 +1020,7 @@
netId,
WifiConfiguration.hiddenSSIDVarName,
Integer.toString(config.hiddenSSID ? 1 : 0))) {
- Log.d(TAG, config.SSID + ": failed to set hiddenSSID: "+
+ loge(config.SSID + ": failed to set hiddenSSID: "+
config.hiddenSSID);
break setVariables;
}
@@ -1040,7 +1037,7 @@
netId,
varName,
value)) {
- Log.d(TAG, config.SSID + ": failed to set " + varName +
+ loge(config.SSID + ": failed to set " + varName +
": " + value);
break setVariables;
}
@@ -1052,9 +1049,7 @@
if (updateFailed) {
if (newNetwork) {
WifiNative.removeNetworkCommand(netId);
- Log.d(TAG,
- "Failed to set a network variable, removed network: "
- + netId);
+ loge("Failed to set a network variable, removed network: " + netId);
}
return new NetworkUpdateResult(INVALID_NETWORK_ID);
}
@@ -1130,7 +1125,7 @@
/* Ignore */
break;
default:
- Log.e(TAG, "Ignore invalid ip assignment during write");
+ loge("Ignore invalid ip assignment during write");
break;
}
@@ -1154,7 +1149,7 @@
/* Ignore */
break;
default:
- Log.e(TAG, "Ignore invalid proxy configuration during write");
+ loge("Ignore invalid proxy configuration during write");
break;
}
@@ -1163,7 +1158,7 @@
} else {
currentConfig.ipAssignment = newConfig.ipAssignment;
addIpSettingsFromConfig(linkProperties, newConfig);
- Log.d(TAG, "IP config changed SSID = " + currentConfig.SSID + " linkProperties: " +
+ log("IP config changed SSID = " + currentConfig.SSID + " linkProperties: " +
linkProperties.toString());
}
@@ -1173,9 +1168,9 @@
} else {
currentConfig.proxySettings = newConfig.proxySettings;
linkProperties.setHttpProxy(newConfig.linkProperties.getHttpProxy());
- Log.d(TAG, "proxy changed SSID = " + currentConfig.SSID);
+ log("proxy changed SSID = " + currentConfig.SSID);
if (linkProperties.getHttpProxy() != null) {
- Log.d(TAG, " proxyProperties: " + linkProperties.getHttpProxy().toString());
+ log(" proxyProperties: " + linkProperties.getHttpProxy().toString());
}
}
@@ -1394,7 +1389,7 @@
// if we ever get here, we should probably add the
// value to WifiConfiguration to reflect that it's
// supported by the WPA supplicant
- Log.w(TAG, "Failed to look-up a string: " + string);
+ loge("Failed to look-up a string: " + string);
return -1;
}
@@ -1431,4 +1426,12 @@
public static String getConfigFile() {
return ipConfigFile;
}
+
+ private static void loge(String s) {
+ Log.e(TAG, s);
+ }
+
+ private static void log(String s) {
+ Log.d(TAG, s);
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index d1522fb..5ca7aff 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -75,7 +75,6 @@
import android.util.EventLog;
import android.util.Log;
import android.util.LruCache;
-import android.util.Slog;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.AsyncChannel;
@@ -1104,12 +1103,12 @@
mNwService.setInterfaceConfig(intf, ifcg);
}
} catch (Exception e) {
- Log.e(TAG, "Error configuring interface " + intf + ", :" + e);
+ loge("Error configuring interface " + intf + ", :" + e);
return false;
}
if(mCm.tether(intf) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
- Log.e(TAG, "Error tethering on " + intf);
+ loge("Error tethering on " + intf);
return false;
}
return true;
@@ -1135,11 +1134,11 @@
mNwService.setInterfaceConfig(mInterfaceName, ifcg);
}
} catch (Exception e) {
- Log.e(TAG, "Error resetting interface " + mInterfaceName + ", :" + e);
+ loge("Error resetting interface " + mInterfaceName + ", :" + e);
}
if (mCm.untether(mInterfaceName) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
- Log.e(TAG, "Untether initiate failed!");
+ loge("Untether initiate failed!");
}
}
@@ -1175,12 +1174,12 @@
mBatteryStats.noteWifiOff();
}
} catch (RemoteException e) {
- Log.e(TAG, "Failed to note battery stats in wifi");
+ loge("Failed to note battery stats in wifi");
}
mWifiState.set(wifiState);
- if (DBG) Log.d(TAG, "setWifiState: " + syncGetWifiStateByName());
+ if (DBG) log("setWifiState: " + syncGetWifiStateByName());
final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -1199,13 +1198,13 @@
mBatteryStats.noteWifiOff();
}
} catch (RemoteException e) {
- Log.d(TAG, "Failed to note battery stats in wifi");
+ loge("Failed to note battery stats in wifi");
}
// Update state
mWifiApState.set(wifiApState);
- if (DBG) Log.d(TAG, "setWifiApState: " + syncGetWifiApStateByName());
+ if (DBG) log("setWifiApState: " + syncGetWifiApStateByName());
final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -1291,7 +1290,7 @@
}
}
} else {
- Log.w(TAG, "Misformatted scan result text with " +
+ loge("Misformatted scan result text with " +
result.length + " fields: " + line);
}
}
@@ -1419,15 +1418,15 @@
private void setHighPerfModeEnabledNative(boolean enable) {
if(!WifiNative.setSuspendOptimizationsCommand(!enable)) {
- Log.e(TAG, "set suspend optimizations failed!");
+ loge("set suspend optimizations failed!");
}
if (enable) {
if (!WifiNative.setPowerModeCommand(POWER_MODE_ACTIVE)) {
- Log.e(TAG, "set power mode active failed!");
+ loge("set power mode active failed!");
}
} else {
if (!WifiNative.setPowerModeCommand(POWER_MODE_AUTO)) {
- Log.e(TAG, "set power mode auto failed!");
+ loge("set power mode auto failed!");
}
}
}
@@ -1442,7 +1441,10 @@
mLinkProperties.setHttpProxy(WifiConfigStore.getProxyProperties(mLastNetworkId));
}
mLinkProperties.setInterfaceName(mInterfaceName);
- Log.d(TAG, "netId=" + mLastNetworkId + " Link configured: " + mLinkProperties.toString());
+ if (DBG) {
+ log("netId=" + mLastNetworkId + " Link configured: " +
+ mLinkProperties.toString());
+ }
}
private int getMaxDhcpRetries() {
@@ -1503,8 +1505,11 @@
* @param state the new @{code DetailedState}
*/
private void setNetworkDetailedState(NetworkInfo.DetailedState state) {
- Log.d(TAG, "setDetailed state, old ="
- + mNetworkInfo.getDetailedState() + " and new state=" + state);
+ if (DBG) {
+ log("setDetailed state, old ="
+ + mNetworkInfo.getDetailedState() + " and new state=" + state);
+ }
+
if (state != mNetworkInfo.getDetailedState()) {
mNetworkInfo.setDetailedState(state, null, null);
}
@@ -1547,7 +1552,7 @@
* using the interface, stopping DHCP & disabling interface
*/
private void handleNetworkDisconnect() {
- Log.d(TAG, "Stopping DHCP and clearing IP");
+ if (DBG) log("Stopping DHCP and clearing IP");
/*
* stop DHCP
@@ -1562,7 +1567,7 @@
mNwService.clearInterfaceAddresses(mInterfaceName);
mNwService.disableIpv6(mInterfaceName);
} catch (Exception e) {
- Log.e(TAG, "Failed to clear addresses or disable ipv6" + e);
+ loge("Failed to clear addresses or disable ipv6" + e);
}
/* Reset data structures */
@@ -1647,8 +1652,10 @@
linkProperties.setHttpProxy(WifiConfigStore.getProxyProperties(mLastNetworkId));
linkProperties.setInterfaceName(mInterfaceName);
if (!linkProperties.equals(mLinkProperties)) {
- Log.d(TAG, "Link configuration changed for netId: " + mLastNetworkId
- + " old: " + mLinkProperties + "new: " + linkProperties);
+ if (DBG) {
+ log("Link configuration changed for netId: " + mLastNetworkId
+ + " old: " + mLinkProperties + "new: " + linkProperties);
+ }
mLinkProperties = linkProperties;
sendLinkConfigurationChangedBroadcast();
}
@@ -1660,7 +1667,7 @@
}
private void handleFailedIpConfiguration() {
- Log.e(TAG, "IP configuration failed");
+ loge("IP configuration failed");
mWifiInfo.setInetAddress(null);
/**
@@ -1668,7 +1675,7 @@
* to a given network, disable the network
*/
if (++mReconnectCount > getMaxDhcpRetries()) {
- Log.e(TAG, "Failed " +
+ loge("Failed " +
mReconnectCount + " times, Disabling " + mLastNetworkId);
WifiConfigStore.disableNetwork(mLastNetworkId,
WifiConfiguration.DISABLED_DHCP_FAILURE);
@@ -1697,12 +1704,12 @@
try {
mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
} catch (Exception e) {
- Log.e(TAG, "Exception in softap start " + e);
+ loge("Exception in softap start " + e);
try {
mNwService.stopAccessPoint(mInterfaceName);
mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
} catch (Exception e1) {
- Log.e(TAG, "Exception in softap re-start " + e1);
+ loge("Exception in softap re-start " + e1);
return false;
}
}
@@ -1716,17 +1723,17 @@
class DefaultState extends State {
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch (message.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
mWifiP2pChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
} else {
- Log.e(TAG, "WifiP2pService connection failure, error=" + message.arg1);
+ loge("WifiP2pService connection failure, error=" + message.arg1);
}
break;
case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
- Log.e(TAG, "WifiP2pService channel lost, message.arg1 =" + message.arg1);
+ loge("WifiP2pService channel lost, message.arg1 =" + message.arg1);
//TODO: Re-establish connection to state machine after a delay
//mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger());
break;
@@ -1812,7 +1819,7 @@
deferMessage(message);
break;
default:
- Log.e(TAG, "Error! unhandled message" + message);
+ loge("Error! unhandled message" + message);
break;
}
return HANDLED;
@@ -1823,7 +1830,7 @@
@Override
//TODO: could move logging into a common class
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
// [31-8] Reserved for future use
// [7 - 0] HSM state change
// 50021 wifi_state_changed (custom|1|5)
@@ -1853,9 +1860,9 @@
try {
mNwService.disableIpv6(mInterfaceName);
} catch (RemoteException re) {
- Log.e(TAG, "Failed to disable IPv6: " + re);
+ loge("Failed to disable IPv6: " + re);
} catch (IllegalStateException e) {
- Log.e(TAG, "Failed to disable IPv6: " + e);
+ loge("Failed to disable IPv6: " + e);
}
}
}
@@ -1863,7 +1870,7 @@
class DriverLoadingState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
final Message message = new Message();
@@ -1885,10 +1892,10 @@
}
if(WifiNative.loadDriver()) {
- Log.d(TAG, "Driver load successful");
+ if (DBG) log("Driver load successful");
sendMessage(CMD_LOAD_DRIVER_SUCCESS);
} else {
- Log.e(TAG, "Failed to load driver!");
+ loge("Failed to load driver!");
switch(message.arg1) {
case WIFI_STATE_ENABLING:
setWifiState(WIFI_STATE_UNKNOWN);
@@ -1906,7 +1913,7 @@
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch (message.what) {
case CMD_LOAD_DRIVER_SUCCESS:
transitionTo(mDriverLoadedState);
@@ -1942,12 +1949,12 @@
class DriverLoadedState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case CMD_UNLOAD_DRIVER:
transitionTo(mDriverUnloadingState);
@@ -1956,7 +1963,7 @@
try {
mNwService.wifiFirmwareReload(mInterfaceName, "STA");
} catch (Exception e) {
- Log.e(TAG, "Failed to reload STA firmware " + e);
+ loge("Failed to reload STA firmware " + e);
// continue
}
try {
@@ -1967,17 +1974,17 @@
//Set privacy extensions
mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
} catch (RemoteException re) {
- if (DBG) Log.w(TAG, "Unable to change interface settings: " + re);
+ loge("Unable to change interface settings: " + re);
} catch (IllegalStateException ie) {
- if (DBG) Log.w(TAG, "Unable to change interface settings: " + ie);
+ loge("Unable to change interface settings: " + ie);
}
if(WifiNative.startSupplicant()) {
- Log.d(TAG, "Supplicant start successful");
+ if (DBG) log("Supplicant start successful");
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
} else {
- Log.e(TAG, "Failed to start supplicant!");
+ loge("Failed to start supplicant!");
sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
}
break;
@@ -1995,17 +2002,17 @@
class DriverUnloadingState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
final Message message = new Message();
message.copyFrom(getCurrentMessage());
new Thread(new Runnable() {
public void run() {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
mWakeLock.acquire();
if(WifiNative.unloadDriver()) {
- Log.d(TAG, "Driver unload successful");
+ if (DBG) log("Driver unload successful");
sendMessage(CMD_UNLOAD_DRIVER_SUCCESS);
switch(message.arg1) {
@@ -2019,7 +2026,7 @@
break;
}
} else {
- Log.e(TAG, "Failed to unload driver!");
+ loge("Failed to unload driver!");
sendMessage(CMD_UNLOAD_DRIVER_FAILURE);
switch(message.arg1) {
@@ -2040,7 +2047,7 @@
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch (message.what) {
case CMD_UNLOAD_DRIVER_SUCCESS:
transitionTo(mDriverUnloadedState);
@@ -2076,12 +2083,12 @@
class DriverUnloadedState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch (message.what) {
case CMD_LOAD_DRIVER:
mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING);
@@ -2101,12 +2108,12 @@
class DriverFailedState extends State {
@Override
public void enter() {
- Log.e(TAG, getName() + "\n");
+ loge(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
return NOT_HANDLED;
}
}
@@ -2115,15 +2122,15 @@
class SupplicantStartingState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case WifiMonitor.SUP_CONNECTION_EVENT:
- Log.d(TAG, "Supplicant connection established");
+ if (DBG) log("Supplicant connection established");
setWifiState(WIFI_STATE_ENABLED);
mSupplicantRestartCount = 0;
/* Reset the supplicant state to indicate the supplicant
@@ -2144,12 +2151,12 @@
break;
case WifiMonitor.SUP_DISCONNECTION_EVENT:
if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) {
- Log.e(TAG, "Failed to setup control channel, restart supplicant");
+ loge("Failed to setup control channel, restart supplicant");
WifiNative.killSupplicant();
transitionTo(mDriverLoadedState);
sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
} else {
- Log.e(TAG, "Failed " + mSupplicantRestartCount +
+ loge("Failed " + mSupplicantRestartCount +
" times to start supplicant, unload driver");
mSupplicantRestartCount = 0;
transitionTo(mDriverLoadedState);
@@ -2184,7 +2191,7 @@
class SupplicantStartedState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
/* Initialize for connect mode operation at start */
mIsScanMode = false;
@@ -2198,7 +2205,7 @@
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
WifiConfiguration config;
boolean eventLoggingEnabled = true;
switch(message.what) {
@@ -2206,7 +2213,7 @@
transitionTo(mSupplicantStoppingState);
break;
case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */
- Log.e(TAG, "Connection lost, restart supplicant");
+ loge("Connection lost, restart supplicant");
WifiNative.killSupplicant();
WifiNative.closeSupplicantConnection();
mNetworkInfo.setIsAvailable(false);
@@ -2270,7 +2277,7 @@
break;
/* Cannot start soft AP while in client mode */
case CMD_START_AP:
- Log.d(TAG, "Failed to start soft AP with a running supplicant");
+ loge("Failed to start soft AP with a running supplicant");
setWifiApState(WIFI_AP_STATE_FAILED);
break;
case CMD_SET_SCAN_MODE:
@@ -2301,11 +2308,11 @@
class SupplicantStoppingState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- Log.d(TAG, "stopping supplicant");
+ if (DBG) log("stopping supplicant");
if (!WifiNative.stopSupplicant()) {
- Log.e(TAG, "Failed to stop supplicant");
+ loge("Failed to stop supplicant");
}
/* Send ourselves a delayed message to indicate failure after a wait time */
@@ -2321,13 +2328,13 @@
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case WifiMonitor.SUP_CONNECTION_EVENT:
- Log.e(TAG, "Supplicant connection received while stopping");
+ loge("Supplicant connection received while stopping");
break;
case WifiMonitor.SUP_DISCONNECTION_EVENT:
- Log.d(TAG, "Supplicant connection lost");
+ if (DBG) log("Supplicant connection lost");
/* Socket connection can be lost when we do a graceful shutdown
* or when the driver is hung. Ensure supplicant is stopped here.
*/
@@ -2337,7 +2344,7 @@
break;
case CMD_STOP_SUPPLICANT_FAILED:
if (message.arg1 == mSupplicantStopFailureToken) {
- Log.e(TAG, "Timed out on a supplicant stop, kill and proceed");
+ loge("Timed out on a supplicant stop, kill and proceed");
WifiNative.killSupplicant();
WifiNative.closeSupplicantConnection();
transitionTo(mDriverLoadedState);
@@ -2371,12 +2378,12 @@
class DriverStartingState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
SupplicantState state = handleSupplicantStateChange(message);
@@ -2418,7 +2425,7 @@
class DriverStartedState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
mIsRunning = true;
@@ -2459,7 +2466,7 @@
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
boolean eventLoggingEnabled = true;
switch(message.what) {
case CMD_SET_SCAN_TYPE:
@@ -2479,20 +2486,20 @@
break;
case CMD_SET_COUNTRY_CODE:
String country = (String) message.obj;
- Log.d(TAG, "set country code " + country);
+ if (DBG) log("set country code " + country);
if (!WifiNative.setCountryCodeCommand(country.toUpperCase())) {
- Log.e(TAG, "Failed to set country code " + country);
+ loge("Failed to set country code " + country);
}
break;
case CMD_SET_FREQUENCY_BAND:
int band = message.arg1;
- Log.d(TAG, "set frequency band " + band);
+ if (DBG) log("set frequency band " + band);
if (WifiNative.setBandCommand(band)) {
mFrequencyBand.set(band);
//Fetch the latest scan results when frequency band is set
startScan(true);
} else {
- Log.e(TAG, "Failed to set frequency band " + band);
+ loge("Failed to set frequency band " + band);
}
break;
case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE:
@@ -2512,7 +2519,7 @@
} else if (message.arg1 == MULTICAST_V4) {
WifiNative.startFilteringMulticastV4Packets();
} else {
- Log.e(TAG, "Illegal arugments to CMD_START_PACKET_FILTERING");
+ loge("Illegal arugments to CMD_START_PACKET_FILTERING");
}
break;
case CMD_STOP_PACKET_FILTERING:
@@ -2521,7 +2528,7 @@
} else if (message.arg1 == MULTICAST_V4) {
WifiNative.stopFilteringMulticastV4Packets();
} else {
- Log.e(TAG, "Illegal arugments to CMD_STOP_PACKET_FILTERING");
+ loge("Illegal arugments to CMD_STOP_PACKET_FILTERING");
}
break;
default:
@@ -2534,7 +2541,7 @@
}
@Override
public void exit() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
mIsRunning = false;
updateBatteryWorkSource(null);
mScanResults = null;
@@ -2544,12 +2551,12 @@
class DriverStoppingState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
SupplicantState state = handleSupplicantStateChange(message);
@@ -2583,12 +2590,12 @@
class DriverStoppedState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch (message.what) {
case CMD_START_DRIVER:
mWakeLock.acquire();
@@ -2607,12 +2614,12 @@
class ScanModeState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case CMD_SET_SCAN_MODE:
if (message.arg1 == SCAN_ONLY_MODE) {
@@ -2644,12 +2651,12 @@
class ConnectModeState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
StateChangeResult stateChangeResult;
switch(message.what) {
case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
@@ -2696,7 +2703,7 @@
mLastExplicitNetworkId = netId;
mLastNetworkChoiceTime = SystemClock.elapsedRealtime();
mNextWifiActionExplicit = true;
- Slog.d(TAG, "Setting wifi connect explicit for netid " + netId);
+ if (DBG) log("Setting wifi connect explicit for netid " + netId);
/* Expect a disconnection from the old connection */
transitionTo(mDisconnectingState);
break;
@@ -2710,7 +2717,7 @@
/* Handle scan results */
return NOT_HANDLED;
case WifiMonitor.NETWORK_CONNECTION_EVENT:
- Log.d(TAG,"Network connection established");
+ if (DBG) log("Network connection established");
mLastNetworkId = message.arg1;
mLastBssid = (String) message.obj;
@@ -2731,7 +2738,7 @@
transitionTo(mConnectingState);
break;
case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
- Log.d(TAG,"Network connection lost");
+ if (DBG) log("Network connection lost");
handleNetworkDisconnect();
transitionTo(mDisconnectedState);
break;
@@ -2747,15 +2754,15 @@
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
try {
mNwService.enableIpv6(mInterfaceName);
} catch (RemoteException re) {
- Log.e(TAG, "Failed to enable IPv6: " + re);
+ loge("Failed to enable IPv6: " + re);
} catch (IllegalStateException e) {
- Log.e(TAG, "Failed to enable IPv6: " + e);
+ loge("Failed to enable IPv6: " + e);
}
if (!WifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
@@ -2772,20 +2779,20 @@
ifcg.interfaceFlags = "[up]";
try {
mNwService.setInterfaceConfig(mInterfaceName, ifcg);
- Log.v(TAG, "Static IP configuration succeeded");
+ if (DBG) log("Static IP configuration succeeded");
sendMessage(CMD_STATIC_IP_SUCCESS, dhcpInfoInternal);
} catch (RemoteException re) {
- Log.v(TAG, "Static IP configuration failed: " + re);
+ loge("Static IP configuration failed: " + re);
sendMessage(CMD_STATIC_IP_FAILURE);
} catch (IllegalStateException e) {
- Log.v(TAG, "Static IP configuration failed: " + e);
+ loge("Static IP configuration failed: " + e);
sendMessage(CMD_STATIC_IP_FAILURE);
}
}
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
@@ -2856,7 +2863,7 @@
class ConnectedState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
mRssiPollToken++;
if (mEnableRssiPolling) {
@@ -2865,7 +2872,7 @@
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
boolean eventLoggingEnabled = true;
switch (message.what) {
case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
@@ -2921,11 +2928,11 @@
NetworkUpdateResult result = WifiConfigStore.saveNetwork(config);
if (mWifiInfo.getNetworkId() == result.getNetworkId()) {
if (result.hasIpChanged()) {
- Log.d(TAG,"Reconfiguring IP on connection");
+ log("Reconfiguring IP on connection");
transitionTo(mConnectingState);
}
if (result.hasProxyChanged()) {
- Log.d(TAG,"Reconfiguring proxy on connection");
+ log("Reconfiguring proxy on connection");
configureLinkProperties();
sendLinkConfigurationChangedBroadcast();
}
@@ -2977,12 +2984,12 @@
class DisconnectingState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch (message.what) {
case CMD_STOP_DRIVER: /* Stop driver only after disconnect handled */
deferMessage(message);
@@ -3029,7 +3036,7 @@
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
mFrameworkScanIntervalMs = Settings.Secure.getLong(mContext.getContentResolver(),
@@ -3056,7 +3063,7 @@
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch (message.what) {
case CMD_SET_SCAN_MODE:
if (message.arg1 == SCAN_ONLY_MODE) {
@@ -3119,12 +3126,12 @@
class WaitForWpsCompletionState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch (message.what) {
/* Defer all commands that can cause connections to a different network
* or put the state machine out of connect mode
@@ -3139,7 +3146,7 @@
deferMessage(message);
break;
case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
- Log.d(TAG,"Network connection lost");
+ if (DBG) log("Network connection lost");
handleNetworkDisconnect();
break;
case WPS_COMPLETED_EVENT:
@@ -3158,7 +3165,7 @@
class SoftApStartingState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
final Message message = Message.obtain(getCurrentMessage());
@@ -3168,10 +3175,10 @@
new Thread(new Runnable() {
public void run() {
if (startSoftApWithConfig(config)) {
- Log.d(TAG, "Soft AP start successful");
+ if (DBG) log("Soft AP start successful");
sendMessage(CMD_START_AP_SUCCESS);
} else {
- Log.d(TAG, "Soft AP start failed");
+ loge("Soft AP start failed");
sendMessage(CMD_START_AP_FAILURE);
}
}
@@ -3179,7 +3186,7 @@
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case CMD_LOAD_DRIVER:
case CMD_UNLOAD_DRIVER:
@@ -3219,21 +3226,21 @@
class SoftApStartedState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case CMD_STOP_AP:
- Log.d(TAG,"Stopping Soft AP");
+ if (DBG) log("Stopping Soft AP");
setWifiApState(WIFI_AP_STATE_DISABLING);
stopTethering();
try {
mNwService.stopAccessPoint(mInterfaceName);
} catch(Exception e) {
- Log.e(TAG, "Exception in stopAccessPoint()");
+ loge("Exception in stopAccessPoint()");
}
transitionTo(mDriverLoadedState);
break;
@@ -3242,7 +3249,7 @@
break;
/* Fail client mode operation when soft AP is enabled */
case CMD_START_SUPPLICANT:
- Log.e(TAG,"Cannot start supplicant with a running soft AP");
+ loge("Cannot start supplicant with a running soft AP");
setWifiState(WIFI_STATE_UNKNOWN);
break;
case CMD_TETHER_INTERFACE:
@@ -3268,7 +3275,7 @@
private int mSavedArg;
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
//Preserve the argument arg1 that has information used in DriverLoadingState
@@ -3276,7 +3283,7 @@
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case WifiP2pService.WIFI_ENABLE_PROCEED:
//restore argument from original message (CMD_LOAD_DRIVER)
@@ -3311,12 +3318,12 @@
class TetheredState extends State {
@Override
public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
+ if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case CMD_TETHER_INTERFACE:
// Ignore any duplicate interface available notifications
@@ -3327,4 +3334,12 @@
}
}
}
+
+ private void log(String s) {
+ Log.d(TAG, s);
+ }
+
+ private void loge(String s) {
+ Log.e(TAG, s);
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index af8c486..5d5b9ef 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -35,7 +35,6 @@
import android.os.SystemProperties;
import android.provider.Settings;
import android.provider.Settings.Secure;
-import android.util.Slog;
import android.util.Log;
import com.android.internal.util.Protocol;
@@ -67,10 +66,8 @@
*/
public class WifiWatchdogStateMachine extends StateMachine {
-
- private static final boolean VDBG = false;
- private static final boolean DBG = true;
- private static final String WWSM_TAG = "WifiWatchdogStateMachine";
+ private static final boolean DBG = false;
+ private static final String TAG = "WifiWatchdogStateMachine";
private static final String WATCHDOG_NOTIFICATION_ID = "Android.System.WifiWatchdog";
private static final int WIFI_SIGNAL_LEVELS = 4;
@@ -192,7 +189,7 @@
* (all other states)
*/
private WifiWatchdogStateMachine(Context context) {
- super(WWSM_TAG);
+ super(TAG);
mContext = context;
mContentResolver = context.getContentResolver();
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -351,7 +348,7 @@
return urlConnection.getResponseCode() != 204;
} catch (IOException e) {
if (DBG) {
- Slog.d(WWSM_TAG, "Walled garden check - probably not a portal: exception ", e);
+ log("Walled garden check - probably not a portal: exception " + e);
}
return false;
} finally {
@@ -443,7 +440,7 @@
if (results == null) {
if (DBG) {
- Slog.d(WWSM_TAG, "updateBssids: Got null scan results!");
+ log("updateBssids: Got null scan results!");
}
return;
}
@@ -451,7 +448,7 @@
for (ScanResult result : results) {
if (result == null || result.SSID == null) {
if (DBG) {
- Slog.d(WWSM_TAG, "Received invalid scan result: " + result);
+ log("Received invalid scan result: " + result);
}
continue;
}
@@ -461,8 +458,8 @@
}
private void resetWatchdogState() {
- if (VDBG) {
- Slog.v(WWSM_TAG, "Resetting watchdog state...");
+ if (DBG) {
+ log("Resetting watchdog state...");
}
mConnectionInfo = null;
mDisableAPNextFailure = false;
@@ -522,13 +519,13 @@
switch (msg.what) {
case EVENT_WATCHDOG_SETTINGS_CHANGE:
updateSettings();
- if (VDBG) {
- Slog.d(WWSM_TAG, "Updating wifi-watchdog secure settings");
+ if (DBG) {
+ log("Updating wifi-watchdog secure settings");
}
return HANDLED;
}
- if (VDBG) {
- Slog.v(WWSM_TAG, "Caught message " + msg.what + " in state " +
+ if (DBG) {
+ log("Caught message " + msg.what + " in state " +
getCurrentState().getName());
}
return HANDLED;
@@ -553,7 +550,7 @@
public void enter() {
resetWatchdogState();
mContext.registerReceiver(mBroadcastReceiver, mIntentFilter);
- Slog.i(WWSM_TAG, "WifiWatchdogService enabled");
+ if (DBG) log("WifiWatchdogService enabled");
}
@Override
@@ -574,12 +571,12 @@
WifiInfo wifiInfo = (WifiInfo)
stateChangeIntent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
if (wifiInfo == null) {
- Slog.e(WWSM_TAG, "Connected --> WifiInfo object null!");
+ loge("Connected --> WifiInfo object null!");
return HANDLED;
}
if (wifiInfo.getSSID() == null || wifiInfo.getBSSID() == null) {
- Slog.e(WWSM_TAG, "Received wifiInfo object with null elts: "
+ loge("Received wifiInfo object with null elts: "
+ wifiInfoToStr(wifiInfo));
return HANDLED;
}
@@ -598,7 +595,7 @@
return HANDLED;
case EVENT_WIFI_RADIO_STATE_CHANGE:
if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING) {
- Slog.i(WWSM_TAG, "WifiStateDisabling -- Resetting WatchdogState");
+ if (DBG) log("WifiStateDisabling -- Resetting WatchdogState");
resetWatchdogState();
mNetEventCounter++;
transitionTo(mNotConnectedState);
@@ -613,8 +610,8 @@
* @param wifiInfo Info object with non-null ssid and bssid
*/
private void initConnection(WifiInfo wifiInfo) {
- if (VDBG) {
- Slog.v(WWSM_TAG, "Connected:: old " + wifiInfoToStr(mConnectionInfo) +
+ if (DBG) {
+ log("Connected:: old " + wifiInfoToStr(mConnectionInfo) +
" ==> new " + wifiInfoToStr(wifiInfo));
}
@@ -628,7 +625,7 @@
@Override
public void exit() {
mContext.unregisterReceiver(mBroadcastReceiver);
- Slog.i(WWSM_TAG, "WifiWatchdogService disabled");
+ if (DBG) log("WifiWatchdogService disabled");
}
}
@@ -671,7 +668,7 @@
if (DBG) {
dnsCheckLogStr = String.format("Pinging %s on ssid [%s]: ",
mDnsList, mConnectionInfo.getSSID());
- Slog.d(WWSM_TAG, dnsCheckLogStr);
+ log(dnsCheckLogStr);
}
idDnsMap.clear();
@@ -694,7 +691,7 @@
Integer dnsServerId = idDnsMap.get(pingID);
if (dnsServerId == null) {
- Slog.w(WWSM_TAG, "Received a Dns response with unknown ID!");
+ loge("Received a Dns response with unknown ID!");
return HANDLED;
}
@@ -722,7 +719,7 @@
if (dnsCheckSuccesses[dnsServerId] >= mMinDnsResponses) {
// DNS CHECKS OK, NOW WALLED GARDEN
if (DBG) {
- Slog.d(WWSM_TAG, makeLogString() + " SUCCESS");
+ log(makeLogString() + " SUCCESS");
}
if (!shouldCheckWalledGarden()) {
@@ -732,13 +729,10 @@
mLastWalledGardenCheckTime = SystemClock.elapsedRealtime();
if (isWalledGardenConnection()) {
- if (DBG)
- Slog.d(WWSM_TAG,
- "Walled garden test complete - walled garden detected");
+ if (DBG) log("Walled garden test complete - walled garden detected");
transitionTo(mWalledGardenState);
} else {
- if (DBG)
- Slog.d(WWSM_TAG, "Walled garden test complete - online");
+ if (DBG) log("Walled garden test complete - online");
transitionTo(mOnlineWatchState);
}
return HANDLED;
@@ -746,7 +740,7 @@
if (idDnsMap.isEmpty()) {
if (DBG) {
- Slog.d(WWSM_TAG, makeLogString() + " FAILURE");
+ log(makeLogString() + " FAILURE");
}
transitionTo(mDnsCheckFailureState);
return HANDLED;
@@ -769,15 +763,15 @@
private boolean shouldCheckWalledGarden() {
if (!mWalledGardenTestEnabled) {
- if (VDBG)
- Slog.v(WWSM_TAG, "Skipping walled garden check - disabled");
+ if (DBG)
+ log("Skipping walled garden check - disabled");
return false;
}
long waitTime = waitTime(mWalledGardenIntervalMs,
mLastWalledGardenCheckTime);
if (waitTime > 0) {
if (DBG) {
- Slog.d(WWSM_TAG, "Skipping walled garden check - wait " +
+ log("Skipping walled garden check - wait " +
waitTime + " ms.");
}
return false;
@@ -825,28 +819,28 @@
case EVENT_RSSI_CHANGE:
if (msg.arg1 != mNetEventCounter) {
if (DBG) {
- Slog.d(WWSM_TAG, "Rssi change message out of sync, ignoring");
+ log("Rssi change message out of sync, ignoring");
}
return HANDLED;
}
int newRssi = msg.arg2;
signalUnstable = !rssiStrengthAboveCutoff(newRssi);
- if (VDBG) {
- Slog.v(WWSM_TAG, "OnlineWatchState:: new rssi " + newRssi + " --> level " +
+ if (DBG) {
+ log("OnlineWatchState:: new rssi " + newRssi + " --> level " +
WifiManager.calculateSignalLevel(newRssi, WIFI_SIGNAL_LEVELS));
}
if (signalUnstable && !unstableSignalChecks) {
- if (VDBG) {
- Slog.v(WWSM_TAG, "Sending triggered check msg");
+ if (DBG) {
+ log("Sending triggered check msg");
}
triggerSingleDnsCheck();
}
return HANDLED;
case MESSAGE_SINGLE_DNS_CHECK:
if (msg.arg1 != checkGuard) {
- if (VDBG) {
- Slog.v(WWSM_TAG, "Single check msg out of sync, ignoring.");
+ if (DBG) {
+ log("Single check msg out of sync, ignoring.");
}
return HANDLED;
}
@@ -865,8 +859,8 @@
pingInfoMap.remove(msg.arg1);
int responseTime = msg.arg2;
if (responseTime >= 0) {
- if (VDBG) {
- Slog.v(WWSM_TAG, "Single DNS ping OK. Response time: "
+ if (DBG) {
+ log("Single DNS ping OK. Response time: "
+ responseTime + " from DNS " + curDnsServer);
}
pingInfoMap.clear();
@@ -877,7 +871,7 @@
} else {
if (pingInfoMap.isEmpty()) {
if (DBG) {
- Slog.d(WWSM_TAG, "Single dns ping failure. All dns servers failed, "
+ log("Single dns ping failure. All dns servers failed, "
+ "starting full checks.");
}
transitionTo(mDnsCheckingState);
@@ -924,8 +918,8 @@
}
if (msg.arg1 != mNetEventCounter) {
- if (VDBG) {
- Slog.v(WWSM_TAG, "Msg out of sync, ignoring...");
+ if (DBG) {
+ log("Msg out of sync, ignoring...");
}
return HANDLED;
}
@@ -933,7 +927,7 @@
if (mDisableAPNextFailure || mNumCheckFailures >= mBssids.size()
|| mNumCheckFailures >= mMaxSsidBlacklists) {
if (sWifiOnly) {
- Slog.w(WWSM_TAG, "Would disable bad network, but device has no mobile data!" +
+ log("Would disable bad network, but device has no mobile data!" +
" Going idle...");
// This state should be called idle -- will be changing flow.
transitionTo(mNotConnectedState);
@@ -941,7 +935,7 @@
}
// TODO : Unban networks if they had low signal ?
- Slog.i(WWSM_TAG, "Disabling current SSID " + wifiInfoToStr(mConnectionInfo)
+ log("Disabling current SSID " + wifiInfoToStr(mConnectionInfo)
+ ". " + "numCheckFailures " + mNumCheckFailures
+ ", numAPs " + mBssids.size());
int networkId = mConnectionInfo.getNetworkId();
@@ -955,7 +949,7 @@
}
transitionTo(mNotConnectedState);
} else {
- Slog.i(WWSM_TAG, "Blacklisting current BSSID. " + wifiInfoToStr(mConnectionInfo)
+ log("Blacklisting current BSSID. " + wifiInfoToStr(mConnectionInfo)
+ "numCheckFailures " + mNumCheckFailures + ", numAPs " + mBssids.size());
mWifiManager.addToBlacklist(mConnectionInfo.getBSSID());
@@ -979,8 +973,8 @@
}
if (msg.arg1 != mNetEventCounter) {
- if (VDBG) {
- Slog.v(WWSM_TAG, "WalledGardenState::Msg out of sync, ignoring...");
+ if (DBG) {
+ log("WalledGardenState::Msg out of sync, ignoring...");
}
return HANDLED;
}
@@ -1005,8 +999,8 @@
}
if (msg.arg1 != mNetEventCounter) {
- if (VDBG) {
- Slog.v(WWSM_TAG, "BlacklistedApState::Msg out of sync, ignoring...");
+ if (DBG) {
+ log("BlacklistedApState::Msg out of sync, ignoring...");
}
return HANDLED;
}
@@ -1067,5 +1061,11 @@
return Settings.Secure.putInt(cr, name, value ? 1 : 0);
}
+ private void log(String s) {
+ Log.d(TAG, s);
+ }
+ private void loge(String s) {
+ Log.e(TAG, s);
+ }
}