Merge "Fix bug #2246815 Error popups on EditText should span the width of the screen instead of the width of the EditText field"
diff --git a/api/current.txt b/api/current.txt
index b0621c2..d113e90 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4528,6 +4528,44 @@
field public static final java.lang.String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY = "android.bluetooth.headset.intent.category.companyid";
}
+ public final class BluetoothHealth implements android.bluetooth.BluetoothProfile {
+ method public boolean connectChannelToSource(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration);
+ method public boolean disconnectChannel(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration, int);
+ method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+ method public int getConnectionState(android.bluetooth.BluetoothDevice);
+ method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
+ method public android.os.ParcelFileDescriptor getMainChannelFd(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration);
+ method public boolean registerSinkAppConfiguration(java.lang.String, int, android.bluetooth.BluetoothHealthCallback);
+ method public boolean unregisterAppConfiguration(android.bluetooth.BluetoothHealthAppConfiguration);
+ field public static final int APP_CONFIG_REGISTRATION_FAILURE = 1; // 0x1
+ field public static final int APP_CONFIG_REGISTRATION_SUCCESS = 0; // 0x0
+ field public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3; // 0x3
+ field public static final int APP_CONFIG_UNREGISTRATION_SUCCESS = 2; // 0x2
+ field public static final int CHANNEL_TYPE_RELIABLE = 10; // 0xa
+ field public static final int CHANNEL_TYPE_STREAMING = 11; // 0xb
+ field public static final int SINK_ROLE = 2; // 0x2
+ field public static final int SOURCE_ROLE = 1; // 0x1
+ field public static final int STATE_CHANNEL_CONNECTED = 2; // 0x2
+ field public static final int STATE_CHANNEL_CONNECTING = 1; // 0x1
+ field public static final int STATE_CHANNEL_DISCONNECTED = 0; // 0x0
+ field public static final int STATE_CHANNEL_DISCONNECTING = 3; // 0x3
+ }
+
+ public final class BluetoothHealthAppConfiguration implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getDataType();
+ method public java.lang.String getName();
+ method public int getRole();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
+ public abstract class BluetoothHealthCallback {
+ ctor public BluetoothHealthCallback();
+ method public void onHealthAppConfigurationStatusChange(android.bluetooth.BluetoothHealthAppConfiguration, int);
+ method public void onHealthChannelStateChange(android.bluetooth.BluetoothHealthAppConfiguration, android.bluetooth.BluetoothDevice, int, int, android.os.ParcelFileDescriptor, int);
+ }
+
public abstract interface BluetoothProfile {
method public abstract java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
method public abstract int getConnectionState(android.bluetooth.BluetoothDevice);
@@ -16662,6 +16700,7 @@
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact_entity";
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String DATA_ID = "data_id";
+ field public static final android.net.Uri PROFILE_CONTENT_URI;
}
public static final class ContactsContract.Settings implements android.provider.ContactsContract.SettingsColumns {
@@ -16674,6 +16713,7 @@
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 ANY_UNSYNCED = "any_unsynced";
+ field public static final java.lang.String DATA_SET = "data_set";
field public static final java.lang.String SHOULD_SYNC = "should_sync";
field public static final java.lang.String UNGROUPED_COUNT = "summ_count";
field public static final java.lang.String UNGROUPED_VISIBLE = "ungrouped_visible";
@@ -25917,8 +25957,9 @@
ctor public FrameLayout(android.content.Context);
ctor public FrameLayout(android.content.Context, android.util.AttributeSet);
ctor public FrameLayout(android.content.Context, android.util.AttributeSet, int);
- method public boolean getConsiderGoneChildrenWhenMeasuring();
+ method public deprecated boolean getConsiderGoneChildrenWhenMeasuring();
method public android.graphics.drawable.Drawable getForeground();
+ method public boolean getMeasureAllChildren();
method protected void onLayout(boolean, int, int, int, int);
method public void setForeground(android.graphics.drawable.Drawable);
method public void setForegroundGravity(int);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 41e3fdf..034e3c7 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1638,6 +1638,12 @@
* or later, consider instead using {@link LoaderManager} instead, available
* via {@link #getLoaderManager()}.</em>
*
+ * <p><strong>Warning:</strong> Do not call {@link Cursor#close()} on a cursor obtained using
+ * this method, because the activity will do that for you at the appropriate time. However, if
+ * you call {@link #stopManagingCursor} on a cursor from a managed query, the system <em>will
+ * not</em> automatically close the cursor and, in that case, you must call
+ * {@link Cursor#close()}.</p>
+ *
* @param uri The URI of the content provider to query.
* @param projection List of columns to return.
* @param selection SQL WHERE clause.
@@ -1672,6 +1678,12 @@
* or later, consider instead using {@link LoaderManager} instead, available
* via {@link #getLoaderManager()}.</em>
*
+ * <p><strong>Warning:</strong> Do not call {@link Cursor#close()} on a cursor obtained using
+ * this method, because the activity will do that for you at the appropriate time. However, if
+ * you call {@link #stopManagingCursor} on a cursor from a managed query, the system <em>will
+ * not</em> automatically close the cursor and, in that case, you must call
+ * {@link Cursor#close()}.</p>
+ *
* @param uri The URI of the content provider to query.
* @param projection List of columns to return.
* @param selection SQL WHERE clause.
@@ -1707,6 +1719,12 @@
* or later, consider instead using {@link LoaderManager} instead, available
* via {@link #getLoaderManager()}.</em>
*
+ * <p><strong>Warning:</strong> Do not call {@link Cursor#close()} on cursor obtained from
+ * {@link #managedQuery}, because the activity will do that for you at the appropriate time.
+ * However, if you call {@link #stopManagingCursor} on a cursor from a managed query, the system
+ * <em>will not</em> automatically close the cursor and, in that case, you must call
+ * {@link Cursor#close()}.</p>
+ *
* @param c The Cursor to be managed.
*
* @see #managedQuery(android.net.Uri , String[], String, String[], String)
@@ -1728,6 +1746,10 @@
* {@link #startManagingCursor}, stop the activity's management of that
* cursor.
*
+ * <p><strong>Warning:</strong> After calling this method on a cursor from a managed query,
+ * the system <em>will not</em> automatically close the cursor and you must call
+ * {@link Cursor#close()}.</p>
+ *
* @param c The Cursor that was being managed.
*
* @see #startManagingCursor
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 102fac1..4fe9cef 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1254,6 +1254,12 @@
*/
public ComponentName importanceReasonComponent;
+ /**
+ * When {@link importanceReasonPid} is non-0, this is the importance
+ * of the other pid. @hide
+ */
+ public int importanceReasonImportance;
+
public RunningAppProcessInfo() {
importance = IMPORTANCE_FOREGROUND;
importanceReasonCode = REASON_UNKNOWN;
@@ -1280,6 +1286,7 @@
dest.writeInt(importanceReasonCode);
dest.writeInt(importanceReasonPid);
ComponentName.writeToParcel(importanceReasonComponent, dest);
+ dest.writeInt(importanceReasonImportance);
}
public void readFromParcel(Parcel source) {
@@ -1293,6 +1300,7 @@
importanceReasonCode = source.readInt();
importanceReasonPid = source.readInt();
importanceReasonComponent = ComponentName.readFromParcel(source);
+ importanceReasonImportance = source.readInt();
}
public static final Creator<RunningAppProcessInfo> CREATOR =
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
index 0a01dcf..c165d92 100644
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -32,10 +32,25 @@
* <p>BluetoothHealth is a proxy object for controlling the Bluetooth
* Service via IPC.
*
- * <p> Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothHealth proxy object. Use
- * {@link BluetoothAdapter#closeProfileProxy} to close the service connection.
- * @hide
+ * <p> How to connect to a health device which is acting in the source role.
+ * <li> Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothHealth proxy object. </li>
+ * <li> Create an {@link BluetoothHealth} callback and call
+ * {@link #registerSinkAppConfiguration} to register an application
+ * configuration </li>
+ * <li> Pair with the remote device. This currently needs to be done manually
+ * from Bluetooth Settings </li>
+ * <li> Connect to a health device using {@link #connectChannelToSource}. Some
+ * devices will connect the channel automatically. The {@link BluetoothHealth}
+ * callback will inform the application of channel state change. </li>
+ * <li> Use the file descriptor provided with a connected channel to read and
+ * write data to the health channel. </li>
+ * <li> The received data needs to be interpreted using a health manager which
+ * implements the IEEE 11073-xxxxx specifications.
+ * <li> When done, close the health channel by calling {@link #disconnectChannel}
+ * and unregister the application configuration calling
+ * {@link #unregisterAppConfiguration}
+ *
*/
public final class BluetoothHealth implements BluetoothProfile {
private static final String TAG = "BluetoothHealth";
@@ -137,7 +152,6 @@
*
* @param config The health app configuration
* @return Success or failure.
- * @hide
*/
public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
boolean result = false;
@@ -222,16 +236,15 @@
* @param device The remote Bluetooth device.
* @param config The application configuration which has been registered using
* {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) }
- * @param fd The file descriptor that was associated with the channel.
+ * @param channelId The channel id associated with the channel
* @return If true, the callback associated with the application config will be called.
- * @hide
*/
public boolean disconnectChannel(BluetoothDevice device,
- BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
+ BluetoothHealthAppConfiguration config, int channelId) {
if (mService != null && isEnabled() && isValidDevice(device) &&
config != null) {
try {
- return mService.disconnectChannel(device, config, fd);
+ return mService.disconnectChannel(device, config, channelId);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -248,11 +261,13 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
+ * <p> Its the responsibility of the caller to close the ParcelFileDescriptor
+ * when done.
+ *
* @param device The remote Bluetooth health device
* @param config The application configuration
* @return null on failure, ParcelFileDescriptor on success.
*/
-
public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
BluetoothHealthAppConfiguration config) {
if (mService != null && isEnabled() && isValidDevice(device) &&
@@ -300,7 +315,7 @@
}
/**
- * Get connected devices for this specific profile.
+ * Get connected devices for the health profile.
*
* <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
*
@@ -368,14 +383,15 @@
@Override
public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config,
int status) {
- mCallback.onHealthAppConfigurationStatusChange(config, status);
+ mCallback.onHealthAppConfigurationStatusChange(config, status);
}
@Override
public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config,
BluetoothDevice device, int prevState, int newState,
- ParcelFileDescriptor fd) {
- mCallback.onHealthChannelStateChange(config, device, prevState, newState, fd);
+ ParcelFileDescriptor fd, int channelId) {
+ mCallback.onHealthChannelStateChange(config, device, prevState, newState, fd,
+ channelId);
}
}
@@ -389,13 +405,13 @@
public static final int STATE_CHANNEL_DISCONNECTING = 3;
/** Health App Configuration registration success */
- public static final int APPLICATION_REGISTRATION_SUCCESS = 0;
+ public static final int APP_CONFIG_REGISTRATION_SUCCESS = 0;
/** Health App Configuration registration failure */
- public static final int APPLICATION_REGISTRATION_FAILURE = 1;
+ public static final int APP_CONFIG_REGISTRATION_FAILURE = 1;
/** Health App Configuration un-registration success */
- public static final int APPLICATION_UNREGISTRATION_SUCCESS = 2;
+ public static final int APP_CONFIG_UNREGISTRATION_SUCCESS = 2;
/** Health App Configuration un-registration failure */
- public static final int APPLICATION_UNREGISTRATION_FAILURE = 3;
+ public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3;
private ServiceListener mServiceListener;
private IBluetooth mService;
diff --git a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
index 7020249..15a9101 100644
--- a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
+++ b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
@@ -26,7 +26,6 @@
* that the Bluetooth Health third party application will register to communicate with the
* remote Bluetooth health device.
*
- * @hide
*/
public final class BluetoothHealthAppConfiguration implements Parcelable {
private final String mName;
@@ -39,6 +38,7 @@
*
* @param name Friendly name associated with the application configuration
* @param dataType Data Type of the remote Bluetooth Health device
+ * @hide
*/
BluetoothHealthAppConfiguration(String name, int dataType) {
mName = name;
@@ -54,6 +54,7 @@
* @param dataType Data Type of the remote Bluetooth Health device
* @param role {@link BluetoothHealth#SOURCE_ROLE} or
* {@link BluetoothHealth#SINK_ROLE}
+ * @hide
*/
BluetoothHealthAppConfiguration(String name, int dataType, int role, int
channelType) {
@@ -93,7 +94,6 @@
mChannelType + "]";
}
- @Override
public int describeContents() {
return 0;
}
@@ -132,6 +132,7 @@
* @return One of {@link BluetoothHealth#CHANNEL_TYPE_RELIABLE} or
* {@link BluetoothHealth#CHANNEL_TYPE_STREAMING} or
* {@link BluetoothHealth#CHANNEL_TYPE_ANY}.
+ * @hide
*/
public int getChannelType() {
return mChannelType;
@@ -155,13 +156,10 @@
}
};
- @Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(mName);
out.writeInt(mDataType);
out.writeInt(mRole);
out.writeInt(mChannelType);
}
-
-
}
diff --git a/core/java/android/bluetooth/BluetoothHealthCallback.java b/core/java/android/bluetooth/BluetoothHealthCallback.java
index 0d11bb5..baf2ade 100644
--- a/core/java/android/bluetooth/BluetoothHealthCallback.java
+++ b/core/java/android/bluetooth/BluetoothHealthCallback.java
@@ -21,22 +21,48 @@
import android.util.Log;
/**
- * This class is used for all the {@link BluetoothHealth} callbacks.
- * @hide
+ * This abstract class is used to implement {@link BluetoothHealth} callbacks.
*/
public abstract class BluetoothHealthCallback {
-
private static final String TAG = "BluetoothHealthCallback";
+ /**
+ * Callback to inform change in registration state of the health
+ * application.
+ * <p> This callback is called on the binder thread (not on the UI thread)
+ *
+ * @param config Bluetooth Health app configuration
+ * @param status Success or failure of the registration or unregistration
+ * calls. Can be one of
+ * {@link BluetoothHealth#APP_CONFIG_REGISTRATION_SUCCESS} or
+ * {@link BluetoothHealth#APP_CONFIG_REGISTRATION_FAILURE} or
+ * {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_SUCCESS} or
+ * {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_FAILURE}
+ */
public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config,
- int status) {
- Log.d(TAG, "onHealthAppConfigurationStatusChange: " + config + " Status:" + status);
+ int status) {
+ Log.d(TAG, "onHealthAppConfigurationStatusChange: " + config + "Status: " + status);
}
+ /**
+ * Callback to inform change in channel state.
+ * <p> Its the responsibility of the implementor of this callback to close the
+ * parcel file descriptor when done. This callback is called on the Binder
+ * thread (not the UI thread)
+ *
+ * @param config The Health app configutation
+ * @param device The Bluetooth Device
+ * @param prevState The previous state of the channel
+ * @param newState The new state of the channel.
+ * @param fd The Parcel File Descriptor when the channel state is connected.
+ * @param channelId The id associated with the channel. This id will be used
+ * in future calls like when disconnecting the channel.
+ */
public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config,
- BluetoothDevice device, int prevState, int newState,
- ParcelFileDescriptor fd) {
- Log.d(TAG, "onHealthChannelStateChange: " + config + " Device:" + device +
- "PrevState:" + prevState + "NewState:" + newState + "FileDescriptor:" + fd);
+ BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd,
+ int channelId) {
+ Log.d(TAG, "onHealthChannelStateChange: " + config + "Device: " + device +
+ "prevState:" + prevState + "newState:" + newState + "ParcelFd:" + fd +
+ "ChannelId:" + channelId);
}
}
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index d4e7f7d..fefeb93 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -116,7 +116,7 @@
boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config,
int channelType);
- boolean disconnectChannel(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, in ParcelFileDescriptor fd);
+ boolean disconnectChannel(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, int id);
ParcelFileDescriptor getMainChannelFd(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
List<BluetoothDevice> getConnectedHealthDevices();
List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states);
diff --git a/core/java/android/bluetooth/IBluetoothHealthCallback.aidl b/core/java/android/bluetooth/IBluetoothHealthCallback.aidl
index 9fe5335..0ace9fe 100644
--- a/core/java/android/bluetooth/IBluetoothHealthCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothHealthCallback.aidl
@@ -27,5 +27,6 @@
{
void onHealthAppConfigurationStatusChange(in BluetoothHealthAppConfiguration config, int status);
void onHealthChannelStateChange(in BluetoothHealthAppConfiguration config,
- in BluetoothDevice device, int prevState, int newState, in ParcelFileDescriptor fd);
+ in BluetoothDevice device, int prevState, int newState, in
+ ParcelFileDescriptor fd, int id);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 46712a9..48f94d0 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -239,6 +239,9 @@
* methods of activities and other components are called. Note that you
* <em>must</em> be sure to use {@link #unregisterComponentCallbacks} when
* appropriate in the future; this will not be removed for you.
+ *
+ * @param callback The interface to call. This can be either a
+ * {@link ComponentCallbacks} or {@link ComponentCallbacks2} interface.
*/
public void registerComponentCallbacks(ComponentCallbacks callback) {
getApplicationContext().registerComponentCallbacks(callback);
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index ef6e131..9678d48 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -192,10 +192,10 @@
private static final long SYNC_ALARM_TIMEOUT_MAX = 2 * 60 * 60 * 1000; // two hours
/**
- * The amount of time to wait after attempting a bind before canceling a sync and disabling
- * the sync adapter
+ * The amount of time (in milliseconds) to wait after attempting a bind
+ * before canceling a sync and disabling the sync adapter
*/
- public static final long BIND_TIMEOUT_MS = 30 * 1000;
+ public static final long BIND_TIMEOUT_MS = 5 * 60 * 1000;
public void onAccountsUpdated(Account[] accounts) {
// remember if this was the first time this was called after an update
@@ -924,7 +924,7 @@
mStartTime = SystemClock.elapsedRealtime();
mTimeoutStartTime = mStartTime;
mSyncWakeLock = mSyncHandler.getSyncWakeLock(
- mSyncOperation.account.type, mSyncOperation.authority);
+ mSyncOperation.account, mSyncOperation.authority);
mSyncWakeLock.setWorkSource(new WorkSource(syncAdapterUid));
mSyncWakeLock.acquire();
}
@@ -1365,7 +1365,7 @@
public final SyncNotificationInfo mSyncNotificationInfo = new SyncNotificationInfo();
private Long mAlarmScheduleTime = null;
public final SyncTimeTracker mSyncTimeTracker = new SyncTimeTracker();
- private final HashMap<Pair<String, String>, PowerManager.WakeLock> mWakeLocks =
+ private final HashMap<Pair<Account, String>, PowerManager.WakeLock> mWakeLocks =
Maps.newHashMap();
private volatile CountDownLatch mReadyToRunLatch = new CountDownLatch(1);
@@ -1377,11 +1377,11 @@
}
}
- private PowerManager.WakeLock getSyncWakeLock(String accountType, String authority) {
- final Pair<String, String> wakeLockKey = Pair.create(accountType, authority);
+ private PowerManager.WakeLock getSyncWakeLock(Account account, String authority) {
+ final Pair<Account, String> wakeLockKey = Pair.create(account, authority);
PowerManager.WakeLock wakeLock = mWakeLocks.get(wakeLockKey);
if (wakeLock == null) {
- final String name = SYNC_WAKE_LOCK_PREFIX + "_" + authority + "_" + accountType;
+ final String name = SYNC_WAKE_LOCK_PREFIX + "_" + authority + "_" + account;
wakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name);
wakeLock.setReferenceCounted(false);
mWakeLocks.put(wakeLockKey, wakeLock);
diff --git a/core/java/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java
index 44e7e52..4fc63ed 100644
--- a/core/java/android/inputmethodservice/ExtractEditText.java
+++ b/core/java/android/inputmethodservice/ExtractEditText.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.util.AttributeSet;
import android.view.inputmethod.ExtractedText;
+import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
/***
@@ -142,4 +143,17 @@
@Override public boolean hasFocus() {
return this.isEnabled();
}
+
+ /**
+ * @hide
+ */
+ @Override protected void viewClicked(InputMethodManager imm) {
+ // As an instance of this class is supposed to be owned by IMS,
+ // and it has a reference to the IMS (the current IME),
+ // we just need to call back its onViewClicked() here.
+ // It should be good to avoid unnecessary IPCs by doing this as well.
+ if (mIME != null) {
+ mIME.onViewClicked(false);
+ }
+ }
}
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 88abf1a..65c1bd5 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -195,6 +195,8 @@
intent.getStringExtra(Phone.STATE_KEY));
String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
+ mNetworkInfo.setRoaming(intent.getBooleanExtra(Phone.DATA_NETWORK_ROAMING_KEY,
+ false));
mNetworkInfo.setIsAvailable(!intent.getBooleanExtra(Phone.NETWORK_UNAVAILABLE_KEY,
false));
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 3918cfd..f3be39c 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -102,6 +102,21 @@
this.txPackets = txPackets;
this.operations = operations;
}
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("iface=").append(iface);
+ builder.append(" uid=").append(uid);
+ builder.append(" set=").append(setToString(set));
+ builder.append(" tag=").append(tagToString(tag));
+ builder.append(" rxBytes=").append(rxBytes);
+ builder.append(" rxPackets=").append(rxPackets);
+ builder.append(" txBytes=").append(txBytes);
+ builder.append(" txPackets=").append(txPackets);
+ builder.append(" operations=").append(operations);
+ return builder.toString();
+ }
}
public NetworkStats(long elapsedRealtime, int initialSize) {
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 1f2b342..ca1d0d9 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -34,6 +34,7 @@
import android.database.DatabaseUtils;
import android.graphics.Rect;
import android.net.Uri;
+import android.os.Bundle;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.DisplayMetrics;
@@ -44,6 +45,9 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* <p>
@@ -167,6 +171,22 @@
public static final String STREQUENT_PHONE_ONLY = "strequent_phone_only";
/**
+ * A key to a boolean in the "extras" bundle of the cursor.
+ * The boolean indicates that the provider did not create a snippet and that the client asking
+ * for the snippet should do it (true means the snippeting was deferred to the client).
+ *
+ * @hide
+ */
+ public static final String DEFERRED_SNIPPETING = "deferred_snippeting";
+
+ /**
+ * Key to retrieve the original query on the client side.
+ *
+ * @hide
+ */
+ public static final String DEFERRED_SNIPPETING_QUERY = "deferred_snippeting_query";
+
+ /**
* @hide
*/
public static final class Preferences {
@@ -4357,6 +4377,12 @@
Uri.withAppendedPath(AUTHORITY_URI, "raw_contact_entities");
/**
+ * The content:// style URI for this table, specific to the user's profile.
+ */
+ public static final Uri PROFILE_CONTENT_URI =
+ Uri.withAppendedPath(Profile.CONTENT_URI, "raw_contact_entities");
+
+ /**
* The MIME type of {@link #CONTENT_URI} providing a directory of raw contact entities.
*/
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact_entity";
@@ -4857,6 +4883,19 @@
* @hide
*/
public static final String SNIPPET_ARGS_PARAM_KEY = "snippet_args";
+
+ /**
+ * A key to ask the provider to defer the snippeting to the client if possible.
+ * Value of 1 implies true, 0 implies false when 0 is the default.
+ * When a cursor is returned to the client, it should check for an extra with the name
+ * {@link ContactsContract#DEFERRED_SNIPPETING} in the cursor. If it exists, the client
+ * should do its own snippeting using {@link ContactsContract#snippetize}. If
+ * it doesn't exist, the snippet column in the cursor should already contain a snippetized
+ * string.
+ *
+ * @hide
+ */
+ public static final String DEFERRED_SNIPPETING_KEY = "deferred_snippeting";
}
/**
@@ -7053,6 +7092,18 @@
public static final String ACCOUNT_TYPE = "account_type";
/**
+ * The data set within the account that this row belongs to. This allows
+ * multiple sync adapters for the same account type to distinguish between
+ * each others' data.
+ *
+ * This is empty by default, and is completely optional. It only needs to
+ * be populated if multiple sync adapters are entering distinct data for
+ * the same account type and account name.
+ * <P>Type: TEXT</P>
+ */
+ public static final String DATA_SET = "data_set";
+
+ /**
* Depending on the mode defined by the sync-adapter, this flag controls
* the top-level sync behavior for this data source.
* <p>
@@ -8054,4 +8105,138 @@
public static final String DATA_SET = "com.android.contacts.extra.DATA_SET";
}
}
+
+ /**
+ * Creates a snippet out of the given content that matches the given query.
+ * @param content - The content to use to compute the snippet.
+ * @param displayName - Display name for the contact - if this already contains the search
+ * content, no snippet should be shown.
+ * @param query - String to search for in the content.
+ * @param snippetStartMatch - Marks the start of the matching string in the snippet.
+ * @param snippetEndMatch - Marks the end of the matching string in the snippet.
+ * @param snippetEllipsis - Ellipsis string appended to the end of the snippet (if too long).
+ * @param snippetMaxTokens - Maximum number of words from the snippet that will be displayed.
+ * @return The computed snippet, or null if the snippet could not be computed or should not be
+ * shown.
+ *
+ * @hide
+ */
+ public static String snippetize(String content, String displayName, String query,
+ char snippetStartMatch, char snippetEndMatch, String snippetEllipsis,
+ int snippetMaxTokens) {
+
+ String lowerQuery = query != null ? query.toLowerCase() : null;
+ if (TextUtils.isEmpty(content) || TextUtils.isEmpty(query) ||
+ TextUtils.isEmpty(displayName) || !content.toLowerCase().contains(lowerQuery)) {
+ return null;
+ }
+
+ // If the display name already contains the query term, return empty - snippets should
+ // not be needed in that case.
+ String lowerDisplayName = displayName != null ? displayName.toLowerCase() : "";
+ List<String> nameTokens = new ArrayList<String>();
+ List<Integer> nameTokenOffsets = new ArrayList<Integer>();
+ split(lowerDisplayName.trim(), nameTokens, nameTokenOffsets);
+ for (String nameToken : nameTokens) {
+ if (nameToken.startsWith(lowerQuery)) {
+ return null;
+ }
+ }
+
+ String[] contentLines = content.split("\n");
+
+ // Locate the lines of the content that contain the query term.
+ for (String contentLine : contentLines) {
+ if (contentLine.toLowerCase().contains(lowerQuery)) {
+
+ // Line contains the query string - now search for it at the start of tokens.
+ List<String> lineTokens = new ArrayList<String>();
+ List<Integer> tokenOffsets = new ArrayList<Integer>();
+ split(contentLine.trim(), lineTokens, tokenOffsets);
+
+ // As we find matches against the query, we'll populate this list with the marked
+ // (or unchanged) tokens.
+ List<String> markedTokens = new ArrayList<String>();
+
+ int firstToken = -1;
+ int lastToken = -1;
+ for (int i = 0; i < lineTokens.size(); i++) {
+ String token = lineTokens.get(i);
+ String lowerToken = token.toLowerCase();
+ if (lowerToken.startsWith(lowerQuery)) {
+
+ // Query term matched; surround the token with match markers.
+ markedTokens.add(snippetStartMatch + token + snippetEndMatch);
+
+ // If this is the first token found with a match, mark the token
+ // positions to use for assembling the snippet.
+ if (firstToken == -1) {
+ firstToken =
+ Math.max(0, i - (int) Math.floor(
+ Math.abs(snippetMaxTokens)
+ / 2.0));
+ lastToken =
+ Math.min(lineTokens.size(), firstToken +
+ Math.abs(snippetMaxTokens));
+ }
+ } else {
+ markedTokens.add(token);
+ }
+ }
+
+ // Assemble the snippet by piecing the tokens back together.
+ if (firstToken > -1) {
+ StringBuilder sb = new StringBuilder();
+ if (firstToken > 0) {
+ sb.append(snippetEllipsis);
+ }
+ for (int i = firstToken; i < lastToken; i++) {
+ String markedToken = markedTokens.get(i);
+ String originalToken = lineTokens.get(i);
+ sb.append(markedToken);
+ if (i < lastToken - 1) {
+ // Add the characters that appeared between this token and the next.
+ sb.append(contentLine.substring(
+ tokenOffsets.get(i) + originalToken.length(),
+ tokenOffsets.get(i + 1)));
+ }
+ }
+ if (lastToken < lineTokens.size()) {
+ sb.append(snippetEllipsis);
+ }
+ return sb.toString();
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Pattern for splitting a line into tokens. This matches e-mail addresses as a single token,
+ * otherwise splitting on any group of non-alphanumeric characters.
+ *
+ * @hide
+ */
+ private static Pattern SPLIT_PATTERN =
+ Pattern.compile("([\\w-\\.]+)@((?:[\\w]+\\.)+)([a-zA-Z]{2,4})|[\\w]+");
+
+ /**
+ * Helper method for splitting a string into tokens. The lists passed in are populated with the
+ * tokens and offsets into the content of each token. The tokenization function parses e-mail
+ * addresses as a single token; otherwise it splits on any non-alphanumeric character.
+ * @param content Content to split.
+ * @param tokens List of token strings to populate.
+ * @param offsets List of offsets into the content for each token returned.
+ *
+ * @hide
+ */
+ private static void split(String content, List<String> tokens, List<Integer> offsets) {
+ Matcher matcher = SPLIT_PATTERN.matcher(content);
+ while (matcher.find()) {
+ tokens.add(matcher.group());
+ offsets.add(matcher.start());
+ }
+ }
+
+
}
diff --git a/core/java/android/server/BluetoothAdapterStateMachine.java b/core/java/android/server/BluetoothAdapterStateMachine.java
index 69fbca3..ac46ee2 100644
--- a/core/java/android/server/BluetoothAdapterStateMachine.java
+++ b/core/java/android/server/BluetoothAdapterStateMachine.java
@@ -109,6 +109,8 @@
private static final int DEVICES_DISCONNECT_TIMEOUT = 104;
// Prepare Bluetooth timeout happens
private static final int PREPARE_BLUETOOTH_TIMEOUT = 105;
+ // Bluetooth Powerdown timeout happens
+ private static final int POWER_DOWN_TIMEOUT = 106;
private Context mContext;
private BluetoothService mBluetoothService;
@@ -129,6 +131,8 @@
private static final int PREPARE_BLUETOOTH_TIMEOUT_TIME = 10000;
+ private static final int POWER_DOWN_TIMEOUT_TIME = 5000;
+
BluetoothAdapterStateMachine(Context context, BluetoothService bluetoothService,
BluetoothAdapter bluetoothAdapter) {
super(TAG);
@@ -386,6 +390,11 @@
break;
case USER_TURN_OFF: // ignore
break;
+ case POWER_STATE_CHANGED:
+ if ((Boolean) message.obj) {
+ recoverStateMachine(TURN_HOT, null);
+ }
+ break;
default:
return NOT_HANDLED;
}
@@ -420,14 +429,27 @@
}
break;
case POWER_STATE_CHANGED:
+ removeMessages(POWER_DOWN_TIMEOUT);
if (!((Boolean) message.obj)) {
- transitionTo(mHotOff);
- finishSwitchingOff();
+ if (mPublicState == BluetoothAdapter.STATE_TURNING_OFF) {
+ transitionTo(mHotOff);
+ finishSwitchingOff();
+ }
+ } else {
+ if (mPublicState != BluetoothAdapter.STATE_TURNING_ON) {
+ if (mContext.getResources().getBoolean
+ (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+ recoverStateMachine(TURN_HOT, null);
+ } else {
+ recoverStateMachine(TURN_COLD, null);
+ }
+ }
}
break;
case ALL_DEVICES_DISCONNECTED:
removeMessages(DEVICES_DISCONNECT_TIMEOUT);
mBluetoothService.switchConnectable(false);
+ sendMessageDelayed(POWER_DOWN_TIMEOUT, POWER_DOWN_TIMEOUT_TIME);
break;
case DEVICES_DISCONNECT_TIMEOUT:
sendMessage(ALL_DEVICES_DISCONNECTED);
@@ -439,6 +461,17 @@
deferMessage(obtainMessage(TURN_HOT));
}
break;
+ case POWER_DOWN_TIMEOUT:
+ transitionTo(mHotOff);
+ finishSwitchingOff();
+ // reset the hardware for error recovery
+ Log.e(TAG, "Devices failed to power down, reseting...");
+ deferMessage(obtainMessage(TURN_COLD));
+ if (mContext.getResources().getBoolean
+ (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+ deferMessage(obtainMessage(TURN_HOT));
+ }
+ break;
case USER_TURN_ON:
case AIRPLANE_MODE_OFF:
case AIRPLANE_MODE_ON:
@@ -501,6 +534,7 @@
DEVICES_DISCONNECT_TIMEOUT_TIME);
} else {
mBluetoothService.switchConnectable(false);
+ sendMessageDelayed(POWER_DOWN_TIMEOUT, POWER_DOWN_TIMEOUT_TIME);
}
// we turn all the way to PowerOff with AIRPLANE_MODE_ON
@@ -520,6 +554,12 @@
case PER_PROCESS_TURN_OFF:
perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
break;
+ case POWER_STATE_CHANGED:
+ if ((Boolean) message.obj) {
+ // reset the state machine and send it TURN_ON_CONTINUE message
+ recoverStateMachine(USER_TURN_ON, false);
+ }
+ break;
default:
return NOT_HANDLED;
}
@@ -540,7 +580,7 @@
if (what == PER_PROCESS_TURN_ON) {
isTurningOn = true;
- } else if (what == PER_PROCESS_TURN_OFF) {
+ } else if (what == USER_TURN_OFF) {
isTurningOn = false;
} else {
Log.e(TAG, "enter PerProcessState: wrong msg: " + what);
@@ -568,12 +608,31 @@
}
break;
case POWER_STATE_CHANGED:
+ removeMessages(POWER_DOWN_TIMEOUT);
if (!((Boolean) message.obj)) {
transitionTo(mHotOff);
if (!mContext.getResources().getBoolean
(com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
deferMessage(obtainMessage(TURN_COLD));
}
+ } else {
+ if (!isTurningOn) {
+ recoverStateMachine(TURN_COLD, null);
+ for (IBluetoothStateChangeCallback c:
+ mBluetoothService.getApplicationStateChangeCallbacks()) {
+ perProcessCallback(false, c);
+ deferMessage(obtainMessage(PER_PROCESS_TURN_ON, c));
+ }
+ }
+ }
+ break;
+ case POWER_DOWN_TIMEOUT:
+ transitionTo(mHotOff);
+ Log.e(TAG, "Power-down timed out, resetting...");
+ deferMessage(obtainMessage(TURN_COLD));
+ if (mContext.getResources().getBoolean
+ (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+ deferMessage(obtainMessage(TURN_HOT));
}
break;
case USER_TURN_ON:
@@ -616,10 +675,12 @@
perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
if (mBluetoothService.isApplicationStateChangeTrackerEmpty()) {
mBluetoothService.switchConnectable(false);
+ sendMessageDelayed(POWER_DOWN_TIMEOUT, POWER_DOWN_TIMEOUT_TIME);
}
break;
case AIRPLANE_MODE_ON:
mBluetoothService.switchConnectable(false);
+ sendMessageDelayed(POWER_DOWN_TIMEOUT, POWER_DOWN_TIMEOUT_TIME);
allProcessesCallback(false);
// we turn all the way to PowerOff with AIRPLANE_MODE_ON
deferMessage(obtainMessage(AIRPLANE_MODE_ON));
@@ -699,6 +760,17 @@
mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
}
+ /**
+ * bluetoothd has crashed and recovered, the adapter state machine has to
+ * reset itself and try to return to previous state
+ */
+ private void recoverStateMachine(int what, Object obj) {
+ Log.e(TAG, "Get unexpected power on event, reset with: " + what);
+ transitionTo(mHotOff);
+ deferMessage(obtainMessage(TURN_COLD));
+ deferMessage(obtainMessage(what, obj));
+ }
+
private void dump(PrintWriter pw) {
IState currentState = getCurrentState();
if (currentState == mPowerOff) {
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 6eff796..e4f2d32 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -59,9 +59,8 @@
// from remote device when Android is in Suspend state.
private PowerManager.WakeLock mWakeLock;
- private static final int EVENT_RESTART_BLUETOOTH = 1;
- private static final int EVENT_PAIRING_CONSENT_DELAYED_ACCEPT = 2;
- private static final int EVENT_AGENT_CANCEL = 3;
+ private static final int EVENT_PAIRING_CONSENT_DELAYED_ACCEPT = 1;
+ private static final int EVENT_AGENT_CANCEL = 2;
private static final int CREATE_DEVICE_ALREADY_EXISTS = 1;
private static final int CREATE_DEVICE_SUCCESS = 0;
@@ -75,9 +74,6 @@
public void handleMessage(Message msg) {
String address = null;
switch (msg.what) {
- case EVENT_RESTART_BLUETOOTH:
- mBluetoothService.restart();
- break;
case EVENT_PAIRING_CONSENT_DELAYED_ACCEPT:
address = (String)msg.obj;
if (address != null) {
@@ -375,9 +371,6 @@
} else if (name.equals("Powered")) {
mBluetoothState.sendMessage(BluetoothAdapterStateMachine.POWER_STATE_CHANGED,
propValues[1].equals("true") ? new Boolean(true) : new Boolean(false));
- // bluetoothd has restarted, re-read all our properties.
- // Note: bluez only sends this property change when it restarts.
- onRestartRequired();
} else if (name.equals("DiscoverableTimeout")) {
adapterProperties.setProperty(name, propValues[1]);
}
@@ -1033,14 +1026,6 @@
mBluetoothService.onHealthDeviceChannelChanged(devicePath, channelPath, exists);
}
- private void onRestartRequired() {
- if (mBluetoothService.isEnabled()) {
- Log.e(TAG, "*** A serious error occurred (did bluetoothd crash?) - " +
- "restarting Bluetooth ***");
- mHandler.sendEmptyMessage(EVENT_RESTART_BLUETOOTH);
- }
- }
-
private static void log(String msg) {
Log.d(TAG, msg);
}
diff --git a/core/java/android/server/BluetoothHealthProfileHandler.java b/core/java/android/server/BluetoothHealthProfileHandler.java
index 51c995e..a6ada2b 100644
--- a/core/java/android/server/BluetoothHealthProfileHandler.java
+++ b/core/java/android/server/BluetoothHealthProfileHandler.java
@@ -29,6 +29,8 @@
import android.os.RemoteException;
import android.util.Log;
+import java.io.FileDescriptor;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -47,7 +49,6 @@
private static final boolean DBG = true;
private static BluetoothHealthProfileHandler sInstance;
- private Context mContext;
private BluetoothService mBluetoothService;
private ArrayList<HealthChannel> mHealthChannels;
private HashMap <BluetoothHealthAppConfiguration, String> mHealthAppConfigs;
@@ -76,6 +77,17 @@
mConfig = config;
mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
}
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + (mChannelPath == null ? 0 : mChannelPath.hashCode());
+ result = 31 * result + mDevice.hashCode();
+ result = 31 * result + mConfig.hashCode();
+ result = 31 * result + mState;
+ result = 31 * result + mChannelType;
+ return result;
+ }
}
private final Handler mHandler = new Handler() {
@@ -98,28 +110,38 @@
}
if (path == null) {
- mCallbacks.remove(registerApp);
callHealthApplicationStatusCallback(registerApp,
- BluetoothHealth.APPLICATION_REGISTRATION_FAILURE);
+ BluetoothHealth.APP_CONFIG_REGISTRATION_FAILURE);
+ mCallbacks.remove(registerApp);
} else {
mHealthAppConfigs.put(registerApp, path);
callHealthApplicationStatusCallback(registerApp,
- BluetoothHealth.APPLICATION_REGISTRATION_SUCCESS);
+ BluetoothHealth.APP_CONFIG_REGISTRATION_SUCCESS);
}
break;
case MESSAGE_UNREGISTER_APPLICATION:
BluetoothHealthAppConfiguration unregisterApp =
(BluetoothHealthAppConfiguration) msg.obj;
+
+ // Disconnect all the channels
+ for (HealthChannel chan : mHealthChannels) {
+ if (chan.mConfig.equals(unregisterApp) &&
+ chan.mState != BluetoothHealth.STATE_CHANNEL_DISCONNECTED) {
+ disconnectChannel(chan.mDevice, unregisterApp, chan.hashCode());
+ }
+ }
+
boolean result = mBluetoothService.unregisterHealthApplicationNative(
mHealthAppConfigs.get(unregisterApp));
if (result) {
- mCallbacks.remove(unregisterApp);
callHealthApplicationStatusCallback(unregisterApp,
- BluetoothHealth.APPLICATION_UNREGISTRATION_SUCCESS);
+ BluetoothHealth.APP_CONFIG_UNREGISTRATION_SUCCESS);
+ mCallbacks.remove(unregisterApp);
+ mHealthAppConfigs.remove(unregisterApp);
} else {
callHealthApplicationStatusCallback(unregisterApp,
- BluetoothHealth.APPLICATION_UNREGISTRATION_FAILURE);
+ BluetoothHealth.APP_CONFIG_UNREGISTRATION_FAILURE);
}
break;
case MESSAGE_CONNECT_CHANNEL:
@@ -133,7 +155,8 @@
channelType)) {
int prevState = chan.mState;
int state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
- callHealthChannelCallback(chan.mConfig, chan.mDevice, prevState, state, null);
+ callHealthChannelCallback(chan.mConfig, chan.mDevice, prevState, state, null,
+ chan.hashCode());
mHealthChannels.remove(chan);
}
}
@@ -141,7 +164,6 @@
};
private BluetoothHealthProfileHandler(Context context, BluetoothService service) {
- mContext = context;
mBluetoothService = service;
mHealthAppConfigs = new HashMap<BluetoothHealthAppConfiguration, String>();
mHealthChannels = new ArrayList<HealthChannel>();
@@ -205,7 +227,7 @@
int prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
int state = BluetoothHealth.STATE_CHANNEL_CONNECTING;
- callHealthChannelCallback(config, device, prevState, state, null);
+ callHealthChannelCallback(config, device, prevState, state, null, chan.hashCode());
Message msg = mHandler.obtainMessage(MESSAGE_CONNECT_CHANNEL);
msg.obj = chan;
@@ -235,37 +257,44 @@
}
boolean disconnectChannel(BluetoothDevice device,
- BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
- HealthChannel chan = findChannelByFd(device, config, fd);
- if (chan == null) return false;
+ BluetoothHealthAppConfiguration config, int id) {
+ HealthChannel chan = findChannelById(device, config, id);
+ if (chan == null) {
+ return false;
+ }
String deviceObjectPath =
mBluetoothService.getObjectPathFromAddress(device.getAddress());
- if (mBluetoothService.destroyChannelNative(deviceObjectPath, chan.mChannelPath)) {
- int prevState = chan.mState;
- chan.mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTING;
+
+ mBluetoothService.releaseChannelFdNative(chan.mChannelPath);
+
+ int prevState = chan.mState;
+ chan.mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTING;
+ callHealthChannelCallback(config, device, prevState, chan.mState,
+ null, chan.hashCode());
+
+ if (!mBluetoothService.destroyChannelNative(deviceObjectPath, chan.mChannelPath)) {
+ prevState = chan.mState;
+ chan.mState = BluetoothHealth.STATE_CHANNEL_CONNECTED;
callHealthChannelCallback(config, device, prevState, chan.mState,
- chan.mChannelFd);
- return true;
- } else {
+ chan.mChannelFd, chan.hashCode());
return false;
+ } else {
+ return true;
}
}
- private HealthChannel findChannelByFd(BluetoothDevice device,
- BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
+ private HealthChannel findChannelById(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config, int id) {
for (HealthChannel chan : mHealthChannels) {
- if (chan.mChannelFd.equals(fd) && chan.mDevice.equals(device) &&
- chan.mConfig.equals(config)) return chan;
+ if (chan.hashCode() == id) return chan;
}
return null;
}
- private HealthChannel findChannelByPath(BluetoothDevice device,
- BluetoothHealthAppConfiguration config, String path) {
+ private HealthChannel findChannelByPath(BluetoothDevice device, String path) {
for (HealthChannel chan : mHealthChannels) {
- if (chan.mChannelPath.equals(path) && chan.mDevice.equals(device) &&
- chan.mConfig.equals(config)) return chan;
+ if (path.equals(chan.mChannelPath) && device.equals(chan.mDevice)) return chan;
}
return null;
}
@@ -296,7 +325,15 @@
ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
BluetoothHealthAppConfiguration config) {
HealthChannel chan = getMainChannel(device, config);
- if (chan != null) return chan.mChannelFd;
+ if (chan != null) {
+ ParcelFileDescriptor pfd = null;
+ try {
+ pfd = chan.mChannelFd.dup();
+ return pfd;
+ } catch (IOException e) {
+ return null;
+ }
+ }
String objectPath =
mBluetoothService.getObjectPathFromAddress(device.getAddress());
@@ -308,14 +345,18 @@
// We had no record of the main channel but querying Bluez we got a
// main channel. We might not have received the PropertyChanged yet for
// the main channel creation so update our data structure here.
- chan = findChannelByPath(device, config, mainChannelPath);
+ chan = findChannelByPath(device, mainChannelPath);
if (chan == null) {
errorLog("Main Channel present but we don't have any account of it:" +
device +":" + config);
return null;
}
chan.mMainChannel = true;
- return chan.mChannelFd;
+ try {
+ return chan.mChannelFd.dup();
+ } catch (IOException e) {
+ return null;
+ }
}
/*package*/ void onHealthDevicePropertyChanged(String devicePath,
@@ -334,7 +375,7 @@
BluetoothHealthAppConfiguration config = findHealthApplication(device,
channelPath);
if (config != null) {
- HealthChannel chan = findChannelByPath(device, config, channelPath);
+ HealthChannel chan = findChannelByPath(device, channelPath);
if (chan == null) {
errorLog("Health Channel is not present:" + channelPath);
} else {
@@ -346,21 +387,22 @@
private BluetoothHealthAppConfiguration findHealthApplication(
BluetoothDevice device, String channelPath) {
BluetoothHealthAppConfiguration config = null;
- String configPath = mBluetoothService.getChannelApplicationNative(channelPath);
+ HealthChannel chan = findChannelByPath(device, channelPath);
- if (configPath == null) {
- errorLog("No associated application for Health Channel:" + channelPath);
- return null;
+ if (chan != null) {
+ config = chan.mConfig;
} else {
- for (Entry<BluetoothHealthAppConfiguration, String> e :
- mHealthAppConfigs.entrySet()) {
- if (e.getValue().equals(configPath)) {
- config = e.getKey();
+ String configPath = mBluetoothService.getChannelApplicationNative(channelPath);
+ if (configPath == null) {
+ errorLog("Config path is null for application");
+ } else {
+ for (Entry<BluetoothHealthAppConfiguration, String> e :
+ mHealthAppConfigs.entrySet()) {
+ if (e.getValue().equals(configPath)) {
+ config = e.getKey();
+ }
}
- }
- if (config == null) {
- errorLog("No associated application for application path:" + configPath);
- return null;
+ if (config == null) errorLog("No associated application for path:" + configPath);
}
}
return config;
@@ -375,78 +417,83 @@
if (address == null) return;
BluetoothDevice device = adapter.getRemoteDevice(address);
-
- BluetoothHealthAppConfiguration config = findHealthApplication(device,
- channelPath);
+ BluetoothHealthAppConfiguration config;
int state, prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
ParcelFileDescriptor fd;
HealthChannel channel;
+ config = findHealthApplication(device, channelPath);
- if (config != null) {
- if (exists) {
- fd = mBluetoothService.getChannelFdNative(channelPath);
+ if (exists) {
+ fd = mBluetoothService.getChannelFdNative(channelPath);
+ if (fd == null) {
+ errorLog("Error obtaining fd for channel:" + channelPath);
+ return;
+ }
+ boolean mainChannel =
+ getMainChannel(device, config) == null ? false : true;
+ if (!mainChannel) {
+ String mainChannelPath =
+ mBluetoothService.getMainChannelNative(devicePath);
+ if (mainChannelPath == null) {
+ errorLog("Main Channel Path is null for devicePath:" + devicePath);
+ return;
+ }
+ if (mainChannelPath.equals(channelPath)) mainChannel = true;
+ }
+ channel = findConnectingChannel(device, config);
+ if (channel != null) {
+ channel.mChannelFd = fd;
+ channel.mMainChannel = mainChannel;
+ channel.mChannelPath = channelPath;
+ prevState = channel.mState;
+ } else {
+ channel = new HealthChannel(device, config, fd, mainChannel,
+ channelPath);
+ mHealthChannels.add(channel);
+ prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
+ }
+ state = BluetoothHealth.STATE_CHANNEL_CONNECTED;
+ } else {
+ channel = findChannelByPath(device, channelPath);
+ if (channel == null) {
+ errorLog("Channel not found:" + config + ":" + channelPath);
+ return;
+ }
+ mHealthChannels.remove(channel);
- if (fd == null) {
- errorLog("Error obtaining fd for channel:" + channelPath);
- return;
- }
-
- boolean mainChannel =
- getMainChannel(device, config) == null ? false : true;
- if (!mainChannel) {
- String mainChannelPath =
- mBluetoothService.getMainChannelNative(devicePath);
- if (mainChannelPath == null) {
- errorLog("Main Channel Path is null for devicePath:" + devicePath);
- return;
- }
- if (mainChannelPath.equals(channelPath)) mainChannel = true;
- }
-
- channel = findConnectingChannel(device, config);
- if (channel != null) {
- channel.mChannelFd = fd;
- channel.mMainChannel = mainChannel;
- channel.mChannelPath = channelPath;
- prevState = channel.mState;
- } else {
- channel = new HealthChannel(device, config, fd, mainChannel,
- channelPath);
- mHealthChannels.add(channel);
- prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
- }
- state = BluetoothHealth.STATE_CHANNEL_CONNECTED;
- } else {
- channel = findChannelByPath(device, config, channelPath);
- if (channel == null) {
- errorLog("Channel not found:" + config + ":" + channelPath);
- return;
- }
-
- fd = channel.mChannelFd;
- // CLOSE FD
- mBluetoothService.releaseChannelFdNative(channel.mChannelPath);
- mHealthChannels.remove(channel);
-
- prevState = channel.mState;
- state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
- }
- channel.mState = state;
- callHealthChannelCallback(config, device, prevState, state, fd);
+ channel.mChannelFd = null;
+ prevState = channel.mState;
+ state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
}
+ channel.mState = state;
+ callHealthChannelCallback(config, device, prevState, state, channel.mChannelFd,
+ channel.hashCode());
}
private void callHealthChannelCallback(BluetoothHealthAppConfiguration config,
- BluetoothDevice device, int prevState, int state, ParcelFileDescriptor fd) {
+ BluetoothDevice device, int prevState, int state, ParcelFileDescriptor fd, int id) {
broadcastHealthDeviceStateChange(device, prevState, state);
debugLog("Health Device Callback: " + device + " State Change: "
+ prevState + "->" + state);
+
+ ParcelFileDescriptor dupedFd = null;
+ if (fd != null) {
+ try {
+ dupedFd = fd.dup();
+ } catch (IOException e) {
+ dupedFd = null;
+ errorLog("Exception while duping: " + e);
+ }
+ }
+
IBluetoothHealthCallback callback = mCallbacks.get(config);
if (callback != null) {
try {
- callback.onHealthChannelStateChange(config, device, prevState, state, fd);
- } catch (RemoteException e) {}
+ callback.onHealthChannelStateChange(config, device, prevState, state, dupedFd, id);
+ } catch (RemoteException e) {
+ errorLog("Remote Exception:" + e);
+ }
}
}
@@ -458,7 +505,9 @@
if (callback != null) {
try {
callback.onHealthAppConfigurationStatusChange(config, status);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ errorLog("Remote Exception:" + e);
+ }
}
}
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 55a0624..03180ca 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -95,7 +95,6 @@
private boolean mIsAirplaneSensitive;
private boolean mIsAirplaneToggleable;
private BluetoothAdapterStateMachine mBluetoothState;
- private boolean mRestart = false; // need to call enable() after disable()
private int[] mAdapterSdpHandles;
private ParcelUuid[] mAdapterUuids;
@@ -429,11 +428,6 @@
} finally {
Binder.restoreCallingIdentity(ident);
}
-
- if (mRestart) {
- mRestart = false;
- enable();
- }
}
/**
@@ -456,10 +450,6 @@
// the adapter property could be changed before event loop is stoped, clear it again
mAdapterProperties.clear();
disableNative();
- if (mRestart) {
- mRestart = false;
- enable();
- }
}
/** Bring up BT and persist BT on in settings */
@@ -500,17 +490,6 @@
return true;
}
- /** Forcibly restart Bluetooth if it is on */
- /* package */ synchronized void restart() {
- if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) {
- return;
- }
- mRestart = true;
- if (!disable(false)) {
- mRestart = false;
- }
- }
-
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -2243,11 +2222,11 @@
}
public boolean disconnectChannel(BluetoothDevice device,
- BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
+ BluetoothHealthAppConfiguration config, int id) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
"Need BLUETOOTH permission");
synchronized (mBluetoothHealthProfileHandler) {
- return mBluetoothHealthProfileHandler.disconnectChannel(device, config, fd);
+ return mBluetoothHealthProfileHandler.disconnectChannel(device, config, id);
}
}
diff --git a/core/java/android/text/TextPaint.java b/core/java/android/text/TextPaint.java
index 625d869..afd9892 100644
--- a/core/java/android/text/TextPaint.java
+++ b/core/java/android/text/TextPaint.java
@@ -72,8 +72,15 @@
linkColor = tp.linkColor;
drawableState = tp.drawableState;
density = tp.density;
- underlineColors = tp.underlineColors;
- underlineThicknesses = tp.underlineThicknesses;
+
+ if (tp.underlineColors != null) {
+ if (underlineColors == null || underlineColors.length < tp.underlineCount) {
+ underlineColors = new int[tp.underlineCount];
+ underlineThicknesses = new float[tp.underlineCount];
+ }
+ System.arraycopy(tp.underlineColors, 0, underlineColors, 0, tp.underlineCount);
+ System.arraycopy(tp.underlineThicknesses, 0, underlineThicknesses, 0, tp.underlineCount);
+ }
underlineCount = tp.underlineCount;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fd60813f..4a9c5bd 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9995,6 +9995,7 @@
}
final HardwareCanvas canvas = mDisplayList.start();
+ int restoreCount = 0;
try {
int width = mRight - mLeft;
int height = mBottom - mTop;
@@ -10004,6 +10005,8 @@
canvas.onPreDraw(null);
computeScroll();
+
+ restoreCount = canvas.save();
canvas.translate(-mScrollX, -mScrollY);
mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
mPrivateFlags &= ~DIRTY_MASK;
@@ -10015,6 +10018,7 @@
draw(canvas);
}
} finally {
+ canvas.restoreToCount(restoreCount);
canvas.onPostDraw();
mDisplayList.end();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b3dd071..fb3f6e8 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4543,7 +4543,7 @@
predicate.init(accessibilityId);
View root = ViewRootImpl.this.mView;
View target = root.findViewByPredicate(predicate);
- if (target != null && target.isShown()) {
+ if (target != null && target.getVisibility() == View.VISIBLE) {
info = target.createAccessibilityNodeInfo();
}
} finally {
@@ -4586,7 +4586,7 @@
try {
View root = ViewRootImpl.this.mView;
View target = root.findViewById(viewId);
- if (target != null && target.isShown()) {
+ if (target != null && target.getVisibility() == View.VISIBLE) {
info = target.createAccessibilityNodeInfo();
}
} finally {
@@ -4637,14 +4637,14 @@
ArrayList<View> foundViews = mAttachInfo.mFocusablesTempList;
foundViews.clear();
- View root;
+ View root = null;
if (accessibilityViewId != View.NO_ID) {
root = findViewByAccessibilityId(accessibilityViewId);
} else {
root = ViewRootImpl.this.mView;
}
- if (root == null || !root.isShown()) {
+ if (root == null || root.getVisibility() != View.VISIBLE) {
return;
}
@@ -4659,7 +4659,7 @@
final int viewCount = foundViews.size();
for (int i = 0; i < viewCount; i++) {
View foundView = foundViews.get(i);
- if (foundView.isShown()) {
+ if (foundView.getVisibility() == View.VISIBLE) {
infos.add(foundView.createAccessibilityNodeInfo());
}
}
@@ -4732,7 +4732,7 @@
private boolean performActionFocus(int accessibilityId) {
View target = findViewByAccessibilityId(accessibilityId);
- if (target == null) {
+ if (target == null || target.getVisibility() != View.VISIBLE) {
return false;
}
// Get out of touch mode since accessibility wants to move focus around.
@@ -4742,7 +4742,7 @@
private boolean performActionClearFocus(int accessibilityId) {
View target = findViewByAccessibilityId(accessibilityId);
- if (target == null) {
+ if (target == null || target.getVisibility() != View.VISIBLE) {
return false;
}
if (!target.isFocused()) {
@@ -4754,7 +4754,7 @@
private boolean performActionSelect(int accessibilityId) {
View target = findViewByAccessibilityId(accessibilityId);
- if (target == null) {
+ if (target == null || target.getVisibility() != View.VISIBLE) {
return false;
}
if (target.isSelected()) {
@@ -4766,7 +4766,7 @@
private boolean performActionClearSelection(int accessibilityId) {
View target = findViewByAccessibilityId(accessibilityId);
- if (target == null) {
+ if (target == null || target.getVisibility() != View.VISIBLE) {
return false;
}
if (!target.isSelected()) {
@@ -4783,18 +4783,21 @@
}
mFindByAccessibilityIdPredicate.init(accessibilityId);
View foundView = root.findViewByPredicate(mFindByAccessibilityIdPredicate);
- return (foundView != null && foundView.isShown()) ? foundView : null;
+ if (foundView == null || foundView.getVisibility() != View.VISIBLE) {
+ return null;
+ }
+ return foundView;
}
private final class FindByAccessibilitytIdPredicate implements Predicate<View> {
- public int mSerchedId;
+ public int mSearchedId;
public void init(int searchedId) {
- mSerchedId = searchedId;
+ mSearchedId = searchedId;
}
public boolean apply(View view) {
- return (view.getAccessibilityViewId() == mSerchedId);
+ return (view.getAccessibilityViewId() == mSearchedId);
}
}
}
diff --git a/core/java/android/webkit/HTML5VideoInline.java b/core/java/android/webkit/HTML5VideoInline.java
index 1b9a25e..97dc291 100644
--- a/core/java/android/webkit/HTML5VideoInline.java
+++ b/core/java/android/webkit/HTML5VideoInline.java
@@ -7,6 +7,7 @@
import android.webkit.HTML5VideoViewProxy;
import android.view.Surface;
import android.opengl.GLES20;
+import android.os.PowerManager;
/**
* @hide This is only used by the browser
@@ -51,6 +52,7 @@
public void prepareDataAndDisplayMode(HTML5VideoViewProxy proxy) {
super.prepareDataAndDisplayMode(proxy);
setFrameAvailableListener(proxy);
+ mPlayer.setWakeMode(proxy.getContext(), PowerManager.FULL_WAKE_LOCK);
}
// Pause the play and update the play/pause button
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index b945038..2d10bbe 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -886,9 +886,11 @@
event.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED);
}
- // We first get a chance to populate the event.
- onPopulateAccessibilityEvent(event);
-
+ View selectedView = getSelectedView();
+ if (selectedView != null && selectedView.getVisibility() == VISIBLE) {
+ // We first get a chance to populate the event.
+ onPopulateAccessibilityEvent(event);
+ }
return false;
}
@@ -896,10 +898,7 @@
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
// We send selection events only from AdapterView to avoid
// generation of such event for each child.
- View selectedView = getSelectedView();
- if (selectedView != null) {
- selectedView.dispatchPopulateAccessibilityEvent(event);
- }
+ getSelectedView().dispatchPopulateAccessibilityEvent(event);
}
@Override
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 0b0b812..398a7eb 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -465,23 +465,42 @@
}
/**
- * Determines whether to measure all children or just those in
- * the VISIBLE or INVISIBLE state when measuring. Defaults to false.
+ * Sets whether to consider all children, or just those in
+ * the VISIBLE or INVISIBLE state, when measuring. Defaults to false.
+ *
* @param measureAll true to consider children marked GONE, false otherwise.
* Default value is false.
- *
+ *
* @attr ref android.R.styleable#FrameLayout_measureAllChildren
*/
@android.view.RemotableViewMethod
public void setMeasureAllChildren(boolean measureAll) {
mMeasureAllChildren = measureAll;
}
-
+
/**
- * Determines whether to measure all children or just those in
- * the VISIBLE or INVISIBLE state when measuring.
+ * Determines whether all children, or just those in the VISIBLE or
+ * INVISIBLE state, are considered when measuring.
+ *
+ * @return Whether all children are considered when measuring.
+ *
+ * @deprecated This method is deprecated in favor of
+ * {@link #getMeasureAllChildren() getMeasureAllChildren()}, which was
+ * renamed for consistency with
+ * {@link #setMeasureAllChildren(boolean) setMeasureAllChildren()}.
*/
+ @Deprecated
public boolean getConsiderGoneChildrenWhenMeasuring() {
+ return getMeasureAllChildren();
+ }
+
+ /**
+ * Determines whether all children, or just those in the VISIBLE or
+ * INVISIBLE state, are considered when measuring.
+ *
+ * @return Whether all children are considered when measuring.
+ */
+ public boolean getMeasureAllChildren() {
return mMeasureAllChildren;
}
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index a5cf62e..6edfd59 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -961,7 +961,8 @@
}
for (View view : mTopToBottomLeftToRightSet) {
- if (view.dispatchPopulateAccessibilityEvent(event)) {
+ if (view.getVisibility() == View.VISIBLE
+ && view.dispatchPopulateAccessibilityEvent(event)) {
mTopToBottomLeftToRightSet.clear();
return true;
}
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 9afb625..191c4ca 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -405,7 +405,10 @@
onPopulateAccessibilityEvent(event);
// Dispatch only to the selected tab.
if (mSelectedTab != -1) {
- return getChildTabViewAt(mSelectedTab).dispatchPopulateAccessibilityEvent(event);
+ View tabView = getChildTabViewAt(mSelectedTab);
+ if (tabView != null && tabView.getVisibility() == VISIBLE) {
+ return tabView.dispatchPopulateAccessibilityEvent(event);
+ }
}
return false;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 8d3bbfe..ebe22cc 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5426,8 +5426,8 @@
if (mMovement != null && mText instanceof Editable
&& mLayout != null && onCheckIsTextEditor()) {
InputMethodManager imm = InputMethodManager.peekInstance();
+ viewClicked(imm);
if (imm != null) {
- imm.viewClicked(this);
imm.showSoftInput(this, 0);
}
}
@@ -5740,7 +5740,7 @@
MetaKeyKeyListener.stopSelecting(this, sp);
}
}
-
+
/**
* @hide
*/
@@ -5748,10 +5748,12 @@
if (mInputMethodState != null) {
mInputMethodState.mExtracting = req;
}
- // This stops a possible text selection mode. Maybe not intended.
+ // This would stop a possible selection mode, but no such mode is started in case
+ // extracted mode will start. Some text is selected though, and will trigger an action mode
+ // in the extracted view.
hideControllers();
}
-
+
/**
* Called by the framework in response to a text completion from
* the current input method, provided by it calling
@@ -8340,9 +8342,7 @@
if (touchIsFinished && (isTextEditable() || mTextIsSelectable)) {
// Show the IME, except when selecting in read-only text.
final InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- imm.viewClicked(this);
- }
+ viewClicked(imm);
if (!mTextIsSelectable) {
handled |= imm != null && imm.showSoftInput(this, 0);
}
@@ -9222,21 +9222,23 @@
@Override
public boolean performLongClick() {
+ boolean handled = false;
+ boolean vibrate = true;
+
if (super.performLongClick()) {
mDiscardNextActionUp = true;
- return true;
+ handled = true;
}
- boolean handled = false;
-
// Long press in empty space moves cursor and shows the Paste affordance if available.
- if (!isPositionOnText(mLastDownPositionX, mLastDownPositionY) &&
+ if (!handled && !isPositionOnText(mLastDownPositionX, mLastDownPositionY) &&
mInsertionControllerEnabled) {
final int offset = getOffsetForPosition(mLastDownPositionX, mLastDownPositionY);
stopSelectionActionMode();
Selection.setSelection((Spannable) mText, offset);
getInsertionController().showWithActionPopup();
handled = true;
+ vibrate = false;
}
if (!handled && mSelectionActionMode != null) {
@@ -9258,10 +9260,15 @@
}
// Start a new selection
- handled |= !handled && startSelectionActionMode();
+ if (!handled) {
+ handled = startSelectionActionMode();
+ }
+
+ if (vibrate) {
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ }
if (handled) {
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
mDiscardNextActionUp = true;
}
@@ -10009,14 +10016,22 @@
}
}
- ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
- mSelectionActionMode = startActionMode(actionModeCallback);
- final boolean selectionStarted = mSelectionActionMode != null;
+ final InputMethodManager imm = InputMethodManager.peekInstance();
+ boolean extractedTextModeWillBeStartedFullScreen = !(this instanceof ExtractEditText) &&
+ imm != null && imm.isFullscreenMode();
- if (selectionStarted && !mTextIsSelectable) {
+ // Do not start the action mode when extracted text will show up full screen, thus
+ // immediately hiding the newly created action bar, which would be visually distracting.
+ if (!extractedTextModeWillBeStartedFullScreen) {
+ ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
+ mSelectionActionMode = startActionMode(actionModeCallback);
+ }
+ final boolean selectionStarted = mSelectionActionMode != null ||
+ extractedTextModeWillBeStartedFullScreen;
+
+ if (selectionStarted && !mTextIsSelectable && imm != null) {
// Show the IME to be able to replace text, except when selecting non editable text.
- final InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) imm.showSoftInput(this, 0, null);
+ imm.showSoftInput(this, 0, null);
}
return selectionStarted;
@@ -11304,6 +11319,15 @@
mResolvedDrawables = false;
}
+ /**
+ * @hide
+ */
+ protected void viewClicked(InputMethodManager imm) {
+ if (imm != null) {
+ imm.viewClicked(this);
+ }
+ }
+
@ViewDebug.ExportedProperty(category = "text")
private CharSequence mText;
private CharSequence mTransformed;
@@ -11326,7 +11350,7 @@
private final TextPaint mTextPaint;
private boolean mUserSetTextScaleX;
private final Paint mHighlightPaint;
- private int mHighlightColor = 0x4C33B5E5;
+ private int mHighlightColor = 0x6633B5E5;
/**
* This is temporarily visible to fix bug 3085564 in webView. Do not rely on
* this field being protected. Will be restored as private when lineHeight
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index ba2f5d4..3fba1be 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -58,9 +58,20 @@
private TextView mClearDefaultHint;
private PackageManager mPm;
+ private Intent makeMyIntent() {
+ Intent intent = new Intent(getIntent());
+ // The resolver activity is set to be hidden from recent tasks.
+ // we don't want this attribute to be propagated to the next activity
+ // being launched. Note that if the original Intent also had this
+ // flag set, we are now losing it. That should be a very rare case
+ // and we can live with this.
+ intent.setFlags(intent.getFlags()&~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ return intent;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
- onCreate(savedInstanceState, new Intent(getIntent()),
+ onCreate(savedInstanceState, makeMyIntent(),
getResources().getText(com.android.internal.R.string.whichApplication),
null, null, true);
}
diff --git a/core/java/com/android/internal/view/menu/ListMenuPresenter.java b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
index 146c7ac..e6538b0 100644
--- a/core/java/com/android/internal/view/menu/ListMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
@@ -34,6 +34,8 @@
* MenuPresenter for list-style menus.
*/
public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClickListener {
+ private static final String TAG = "ListMenuPresenter";
+
Context mContext;
LayoutInflater mInflater;
MenuBuilder mMenu;
@@ -76,7 +78,7 @@
public void initForMenu(Context context, MenuBuilder menu) {
if (mThemeRes != 0) {
mContext = new ContextThemeWrapper(context, mThemeRes);
- } else if (mContext == null) {
+ } else if (mContext != null) {
mContext = context;
}
mInflater = LayoutInflater.from(mContext);
diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java
index df2f717..6c11288 100644
--- a/core/java/com/android/internal/widget/AbsActionBarView.java
+++ b/core/java/com/android/internal/widget/AbsActionBarView.java
@@ -15,6 +15,7 @@
*/
package com.android.internal.widget;
+import com.android.internal.R;
import com.android.internal.view.menu.ActionMenuPresenter;
import com.android.internal.view.menu.ActionMenuView;
@@ -23,6 +24,8 @@
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
@@ -32,6 +35,7 @@
protected ActionMenuView mMenuView;
protected ActionMenuPresenter mActionMenuPresenter;
protected ActionBarContainer mSplitView;
+ protected int mContentHeight;
protected Animator mVisibilityAnim;
protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
@@ -52,6 +56,30 @@
super(context, attrs, defStyle);
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ // Action bar can change size on configuration changes.
+ // Reread the desired height from the theme-specified style.
+ TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar,
+ com.android.internal.R.attr.actionBarStyle, 0);
+ setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0));
+ a.recycle();
+ if (mActionMenuPresenter != null) {
+ mActionMenuPresenter.onConfigurationChanged(newConfig);
+ }
+ }
+
+ public void setContentHeight(int height) {
+ mContentHeight = height;
+ requestLayout();
+ }
+
+ public int getContentHeight() {
+ return mContentHeight;
+ }
+
public void setSplitView(ActionBarContainer splitView) {
mSplitView = splitView;
}
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 4fccc32..a631380 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -44,8 +44,6 @@
public class ActionBarContextView extends AbsActionBarView implements AnimatorListener {
private static final String TAG = "ActionBarContextView";
- private int mContentHeight;
-
private CharSequence mTitle;
private CharSequence mSubtitle;
@@ -94,15 +92,7 @@
a.recycle();
}
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- if (mActionMenuPresenter != null) {
- mActionMenuPresenter.onConfigurationChanged(newConfig);
- }
- }
-
- public void setHeight(int height) {
+ public void setContentHeight(int height) {
mContentHeight = height;
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 63b0274..7434df3a 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -84,8 +84,6 @@
private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL;
- private int mContentHeight;
-
private int mNavigationMode;
private int mDisplayOptions = -1;
private CharSequence mTitle;
@@ -257,16 +255,6 @@
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- // Action bar can change size on configuration changes.
- // Reread the desired height from the theme-specified style.
- TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar,
- com.android.internal.R.attr.actionBarStyle, 0);
- setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0));
- a.recycle();
- if (mActionMenuPresenter != null) {
- mActionMenuPresenter.onConfigurationChanged(newConfig);
- }
-
mTitleView = null;
mSubtitleView = null;
mTitleUpView = null;
@@ -277,6 +265,13 @@
if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
initTitle();
}
+
+ if (mTabScrollView != null && mIncludeTabs) {
+ ViewGroup.LayoutParams lp = mTabScrollView.getLayoutParams();
+ lp.width = LayoutParams.WRAP_CONTENT;
+ lp.height = LayoutParams.MATCH_PARENT;
+ mTabScrollView.setAllowCollapse(true);
+ }
}
@Override
@@ -304,15 +299,6 @@
addView(mIndeterminateProgressView);
}
- public void setContentHeight(int height) {
- mContentHeight = height;
- requestLayout();
- }
-
- public int getContentHeight() {
- return mContentHeight;
- }
-
public void setSplitActionBar(boolean splitActionBar) {
if (mSplitActionBar != splitActionBar) {
if (mMenuView != null) {
@@ -957,7 +943,7 @@
}
if (mContextView != null) {
- mContextView.setHeight(getMeasuredHeight());
+ mContextView.setContentHeight(getMeasuredHeight());
}
if (mProgressView != null && mProgressView.getVisibility() != GONE) {
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 5baed75..b7bc366 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -444,7 +444,9 @@
mTextView.setText(null);
}
- setContentDescription(tab.getContentDescription());
+ if (mIconView != null) {
+ mIconView.setContentDescription(tab.getContentDescription());
+ }
}
}
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index b01dcd8..9313d0a 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -760,7 +760,8 @@
jint count = end - start;
sp<TextLayoutCacheValue> value;
#if USE_TEXT_LAYOUT_CACHE
- value = gTextLayoutCache.getValue(paint, textArray, start, count, end, flags);
+ value = TextLayoutCache::getInstance().getValue(paint, textArray, start, count,
+ end, flags);
if (value == NULL) {
LOGE("Cannot get TextLayoutCache value");
return ;
@@ -780,7 +781,8 @@
sp<TextLayoutCacheValue> value;
#if USE_TEXT_LAYOUT_CACHE
- value = gTextLayoutCache.getValue(paint, textArray, start, count, contextCount, flags);
+ value = TextLayoutCache::getInstance().getValue(paint, textArray, start, count,
+ contextCount, flags);
if (value == NULL) {
LOGE("Cannot get TextLayoutCache value");
return ;
diff --git a/core/jni/android/graphics/TextLayout.cpp b/core/jni/android/graphics/TextLayout.cpp
index 7e89a37..fa9a7b7 100644
--- a/core/jni/android/graphics/TextLayout.cpp
+++ b/core/jni/android/graphics/TextLayout.cpp
@@ -257,7 +257,7 @@
sp<TextLayoutCacheValue> value;
#if USE_TEXT_LAYOUT_CACHE
// Return advances from the cache. Compute them if needed
- value = gTextLayoutCache.getValue(
+ value = TextLayoutCache::getInstance().getValue(
paint, chars, start, count, contextCount, dirFlags);
#else
value = new TextLayoutCacheValue();
diff --git a/core/jni/android/graphics/TextLayout.h b/core/jni/android/graphics/TextLayout.h
index 9bb1b92..0a29d78 100644
--- a/core/jni/android/graphics/TextLayout.h
+++ b/core/jni/android/graphics/TextLayout.h
@@ -41,11 +41,6 @@
*/
#define USE_TEXT_LAYOUT_CACHE 1
-
-#if USE_TEXT_LAYOUT_CACHE
- static TextLayoutCache gTextLayoutCache;
-#endif
-
enum {
kBidi_LTR = 0,
kBidi_RTL = 1,
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index f04c5eb5..7f79277 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "TextLayoutCache"
+
#include "TextLayoutCache.h"
#include "TextLayout.h"
@@ -23,6 +25,12 @@
namespace android {
+//--------------------------------------------------------------------------------------------------
+#if USE_TEXT_LAYOUT_CACHE
+ ANDROID_SINGLETON_STATIC_INSTANCE(TextLayoutCache);
+#endif
+//--------------------------------------------------------------------------------------------------
+
TextLayoutCache::TextLayoutCache() :
mCache(GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> >::kUnlimitedCapacity),
mSize(0), mMaxSize(MB(DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB)),
@@ -30,13 +38,6 @@
init();
}
-TextLayoutCache::TextLayoutCache(uint32_t max):
- mCache(GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> >::kUnlimitedCapacity),
- mSize(0), mMaxSize(max),
- mCacheHitCount(0), mNanosecondsSaved(0) {
- init();
-}
-
TextLayoutCache::~TextLayoutCache() {
mCache.clear();
}
@@ -46,25 +47,21 @@
mDebugLevel = readRtlDebugLevel();
mDebugEnabled = mDebugLevel & kRtlDebugCaches;
- LOGD("Using TextLayoutCache debug level: %d - Debug Enabled: %d", mDebugLevel, mDebugEnabled);
+ LOGD("Using debug level: %d - Debug Enabled: %d", mDebugLevel, mDebugEnabled);
mCacheStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
- if (mDebugEnabled) {
- LOGD("TextLayoutCache start time: %lld", mCacheStartTime);
- }
- mInitialized = true;
if (mDebugEnabled) {
+ LOGD("Start time: %lld", mCacheStartTime);
#if RTL_USE_HARFBUZZ
- LOGD("TextLayoutCache is using HARFBUZZ");
+ LOGD("Using HARFBUZZ");
#else
- LOGD("TextLayoutCache is using ICU");
+ LOGD("Using ICU");
#endif
+ LOGD("Initialization is done");
}
- if (mDebugEnabled) {
- LOGD("TextLayoutCache initialization is done");
- }
+ mInitialized = true;
}
/*
@@ -147,8 +144,7 @@
// Cleanup to make some room if needed
if (mSize + size > mMaxSize) {
if (mDebugEnabled) {
- LOGD("TextLayoutCache: need to clean some entries "
- "for making some room for a new entry");
+ LOGD("Need to clean some entries for making some room for a new entry");
}
while (mSize + size > mMaxSize) {
// This will call the callback
@@ -213,7 +209,7 @@
float remainingPercent = 100 * ((mMaxSize - mSize) / ((float)mMaxSize));
float timeRunningInSec = (systemTime(SYSTEM_TIME_MONOTONIC) - mCacheStartTime) / 1000000000;
LOGD("------------------------------------------------");
- LOGD("TextLayoutCache stats");
+ LOGD("Cache stats");
LOGD("------------------------------------------------");
LOGD("pid : %d", getpid());
LOGD("running : %.0f seconds", timeRunningInSec);
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index 10dee87..0d8d71f 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -25,6 +25,7 @@
#include <utils/GenerationCache.h>
#include <utils/Compare.h>
#include <utils/RefBase.h>
+#include <utils/Singleton.h>
#include <SkPaint.h>
#include <SkTemplates.h>
@@ -187,11 +188,11 @@
/**
* Cache of text layout information.
*/
-class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >
+class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >,
+ public Singleton<TextLayoutCache>
{
public:
TextLayoutCache();
- TextLayoutCache(uint32_t maxByteSize);
virtual ~TextLayoutCache();
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index 819449a..292047b 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -1659,6 +1659,7 @@
if (fileDesc == NULL) {
// FileDescriptor constructor has thrown an exception
releaseChannelFdNative(env, object, channelPath);
+ close(fd);
return NULL;
}
@@ -1667,7 +1668,7 @@
if (parcelFileDesc == NULL) {
// ParcelFileDescriptor constructor has thrown an exception
releaseChannelFdNative(env, object, channelPath);
- LOGE("---Parcel File Desc is null");
+ close(fd);
return NULL;
}
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index bcf8e71..395e417 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -477,7 +477,7 @@
#if RTL_USE_HARFBUZZ
sp<TextLayoutCacheValue> value;
#if USE_TEXT_LAYOUT_CACHE
- value = gTextLayoutCache.getValue(paint, text, 0, count, count, flags);
+ value = TextLayoutCache::getInstance().getValue(paint, text, 0, count, count, flags);
if (value == NULL) {
LOGE("Cannot get TextLayoutCache value");
return ;
@@ -507,7 +507,7 @@
#if RTL_USE_HARFBUZZ
sp<TextLayoutCacheValue> value;
#if USE_TEXT_LAYOUT_CACHE
- value = gTextLayoutCache.getValue(paint, text, start, count, contextCount, flags);
+ value = TextLayoutCache::getInstance().getValue(paint, text, start, count, contextCount, flags);
if (value == NULL) {
LOGE("Cannot get TextLayoutCache value");
return ;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3fa4d48..72863a2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -87,9 +87,7 @@
<protected-broadcast android:name="android.bluetooth.device.action.NAME_FAILED" />
<protected-broadcast android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
<protected-broadcast android:name="android.bluetooth.device.action.PAIRING_CANCEL" />
- <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" />
<protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REPLY" />
- <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL" />
<protected-broadcast
android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
@@ -1501,19 +1499,23 @@
android:theme="@style/Theme.Holo.Dialog"
android:label="@string/heavy_weight_switcher_title"
android:finishOnCloseSystemDialogs="true"
- android:excludeFromRecents="true">
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.PlatLogoActivity"
- android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen">
+ android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.DisableCarModeActivity"
android:theme="@style/Theme.NoDisplay"
- android:excludeFromRecents="true">
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.RingtonePickerActivity"
android:theme="@style/Theme.Holo.Dialog.Alert"
android:excludeFromRecents="true"
- android:multiprocess="true">
+ android:multiprocess="true"
+ android:process=":ui">
<intent-filter>
<action android:name="android.intent.action.RINGTONE_PICKER" />
<category android:name="android.intent.category.DEFAULT" />
@@ -1524,18 +1526,21 @@
android:excludeFromRecents="true"
android:exported="true"
android:theme="@android:style/Theme.Holo.Dialog"
- android:label="@string/choose_account_label">
+ android:label="@string/choose_account_label"
+ android:process=":ui">
</activity>
<activity android:name="android.accounts.GrantCredentialsPermissionActivity"
android:excludeFromRecents="true"
android:exported="true"
- android:theme="@android:style/Theme.Holo.DialogWhenLarge">
+ android:theme="@android:style/Theme.Holo.DialogWhenLarge"
+ android:process=":ui">
</activity>
<activity android:name="android.content.SyncActivityTooManyDeletes"
android:theme="@android:style/Theme.Holo.Dialog"
- android:label="@string/sync_too_many_deletes">
+ android:label="@string/sync_too_many_deletes"
+ android:process=":ui">
</activity>
<activity android:name="com.android.server.ShutdownActivity"
@@ -1553,7 +1558,8 @@
<activity android:name="com.android.internal.app.NetInitiatedActivity"
android:theme="@style/Theme.Holo.Dialog.Alert"
- android:excludeFromRecents="true">
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<receiver android:name="com.android.server.BootReceiver" >
diff --git a/core/res/res/values-bg-rBG/donottranslate-cldr.xml b/core/res/res/values-bg-rBG/donottranslate-cldr.xml
deleted file mode 100644
index 4c38ad2..0000000
--- a/core/res/res/values-bg-rBG/donottranslate-cldr.xml
+++ /dev/null
@@ -1,149 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="month_long_standalone_january">януари</string>
- <string name="month_long_standalone_february">февруари</string>
- <string name="month_long_standalone_march">март</string>
- <string name="month_long_standalone_april">април</string>
- <string name="month_long_standalone_may">май</string>
- <string name="month_long_standalone_june">юни</string>
- <string name="month_long_standalone_july">юли</string>
- <string name="month_long_standalone_august">август</string>
- <string name="month_long_standalone_september">септември</string>
- <string name="month_long_standalone_october">октомври</string>
- <string name="month_long_standalone_november">ноември</string>
- <string name="month_long_standalone_december">декември</string>
-
- <string name="month_long_january">януари</string>
- <string name="month_long_february">февруари</string>
- <string name="month_long_march">март</string>
- <string name="month_long_april">април</string>
- <string name="month_long_may">май</string>
- <string name="month_long_june">юни</string>
- <string name="month_long_july">юли</string>
- <string name="month_long_august">август</string>
- <string name="month_long_september">септември</string>
- <string name="month_long_october">октомври</string>
- <string name="month_long_november">ноември</string>
- <string name="month_long_december">декември</string>
-
- <string name="month_medium_january">ян.</string>
- <string name="month_medium_february">февр.</string>
- <string name="month_medium_march">март</string>
- <string name="month_medium_april">апр.</string>
- <string name="month_medium_may">май</string>
- <string name="month_medium_june">юни</string>
- <string name="month_medium_july">юли</string>
- <string name="month_medium_august">авг.</string>
- <string name="month_medium_september">септ.</string>
- <string name="month_medium_october">окт.</string>
- <string name="month_medium_november">ноем.</string>
- <string name="month_medium_december">дек.</string>
-
- <string name="month_shortest_january">я</string>
- <string name="month_shortest_february">ф</string>
- <string name="month_shortest_march">м</string>
- <string name="month_shortest_april">а</string>
- <string name="month_shortest_may">м</string>
- <string name="month_shortest_june">ю</string>
- <string name="month_shortest_july">ю</string>
- <string name="month_shortest_august">а</string>
- <string name="month_shortest_september">с</string>
- <string name="month_shortest_october">о</string>
- <string name="month_shortest_november">н</string>
- <string name="month_shortest_december">д</string>
-
- <string name="day_of_week_long_sunday">неделя</string>
- <string name="day_of_week_long_monday">понеделник</string>
- <string name="day_of_week_long_tuesday">вторник</string>
- <string name="day_of_week_long_wednesday">сряда</string>
- <string name="day_of_week_long_thursday">четвъртък</string>
- <string name="day_of_week_long_friday">петък</string>
- <string name="day_of_week_long_saturday">събота</string>
-
- <string name="day_of_week_medium_sunday">нд</string>
- <string name="day_of_week_medium_monday">пн</string>
- <string name="day_of_week_medium_tuesday">вт</string>
- <string name="day_of_week_medium_wednesday">ср</string>
- <string name="day_of_week_medium_thursday">чт</string>
- <string name="day_of_week_medium_friday">пт</string>
- <string name="day_of_week_medium_saturday">сб</string>
-
- <string name="day_of_week_short_sunday">нд</string>
- <string name="day_of_week_short_monday">пн</string>
- <string name="day_of_week_short_tuesday">вт</string>
- <string name="day_of_week_short_wednesday">ср</string>
- <string name="day_of_week_short_thursday">чт</string>
- <string name="day_of_week_short_friday">пт</string>
- <string name="day_of_week_short_saturday">сб</string>
-
- <string name="day_of_week_shortest_sunday">н</string>
- <string name="day_of_week_shortest_monday">п</string>
- <string name="day_of_week_shortest_tuesday">в</string>
- <string name="day_of_week_shortest_wednesday">с</string>
- <string name="day_of_week_shortest_thursday">ч</string>
- <string name="day_of_week_shortest_friday">п</string>
- <string name="day_of_week_shortest_saturday">с</string>
-
- <string name="am">пр. об.</string>
- <string name="pm">сл. об.</string>
- <string name="yesterday">Вчера</string>
- <string name="today">Днес</string>
- <string name="tomorrow">Утре</string>
-
- <string name="hour_minute_24">%-k:%M</string>
- <string name="hour_minute_ampm">%-l:%M %p</string>
- <string name="hour_minute_cap_ampm">%-l:%M %p</string>
- <string name="twelve_hour_time_format">h:mm a</string>
- <string name="twenty_four_hour_time_format">H:mm</string>
- <string name="numeric_date">%d.%m.%Y</string>
- <string name="numeric_date_format">dd.MM.yyyy</string>
- <string name="numeric_date_template">"%s.%s.%s"</string>
- <string name="month_day_year">%d %B %Y</string>
- <string name="time_of_day">%H:%M:%S</string>
- <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
- <string name="date_time">%2$s %1$s</string>
- <string name="time_date">%1$s %3$s</string>
- <string name="abbrev_month_day_year">%d.%m.%Y</string>
- <string name="month_day">%-e %B</string>
- <string name="month">%-B</string>
- <string name="month_year">%B %Y</string>
- <string name="abbrev_month_day">%-e %b</string>
- <string name="abbrev_month">%b</string>
- <string name="abbrev_month_year">%b %Y</string>
- <string name="time1_time2">%1$s-%2$s</string>
- <string name="date1_date2">%2$s - %5$s</string>
- <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string>
- <string name="numeric_wday1_md1_wday2_md2">%3$s.%2$s, %1$s - %8$s.%7$s, %6$s</string>
- <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
- <string name="numeric_wday1_mdy1_wday2_mdy2">%3$s.%2$s.%4$s, %1$s - %8$s.%7$s.%9$s, %6$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s.%2$s.%4$s, %1$s - %10$s %8$s.%7$s.%9$s, %6$s</string>
- <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %3$s.%2$s, %1$s - %10$s %8$s.%7$s, %6$s</string>
- <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
- <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s, %1$s - %6$s %5$s, %4$s</string>
- <string name="wday1_date1_wday2_date2">%2$s, %1$s - %5$s, %4$s</string>
- <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
- <string name="time_wday_date">%1$s %3$s, %2$s</string>
- <string name="wday_date">%3$s, %2$s</string>
- <string name="time_wday">%1$s %2$s</string>
- <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
- <string name="same_year_wday1_md1_wday2_md2">%3$s %2$s, %1$s - %8$s %7$s, %6$s</string>
- <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
- <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s, %1$s - %10$s %8$s %7$s, %6$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s, %1$s - %10$s %8$s %7$s, %6$s</string>
- <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
- <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s, %1$s - %10$s %8$s %7$s %9$s, %6$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s, %1$s - %10$s %8$s %7$s %9$s, %6$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%3$s %2$s %4$s, %1$s - %8$s %7$s %9$s, %6$s</string>
- <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
- <string name="same_month_wday1_md1_wday2_md2">%3$s %2$s, %1$s - %8$s %7$s, %6$s</string>
- <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
- <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
- <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s %9$s, %1$s - %8$s %7$s y, %6$s</string>
- <string name="short_format_month">%b</string>
- <string name="full_wday_month_day_no_year">EEEE MMMM d</string>
- <string name="abbrev_wday_month_day_year">d MMM yyyy, E</string>
-</resources>
diff --git a/core/res/res/values-bg/donottranslate-cldr.xml b/core/res/res/values-bg/donottranslate-cldr.xml
index 62f550a..dc8b3ad 100644
--- a/core/res/res/values-bg/donottranslate-cldr.xml
+++ b/core/res/res/values-bg/donottranslate-cldr.xml
@@ -128,22 +128,22 @@
<string name="wday_date">%3$s, %2$s</string>
<string name="time_wday">%1$s %2$s</string>
<string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
- <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%3$s %2$s, %1$s - %8$s %7$s, %6$s</string>
<string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
<string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s, %1$s - %10$s %8$s %7$s, %6$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s, %1$s - %10$s %8$s %7$s, %6$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
<string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s, %1$s - %10$s %8$s %7$s %9$s, %6$s</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s, %1$s - %10$s %8$s %7$s %9$s, %6$s</string>
<string name="same_month_wday1_mdy1_wday2_mdy2">%3$s %2$s %4$s, %1$s - %8$s %7$s %9$s, %6$s</string>
<string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
- <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%3$s %2$s, %1$s - %8$s %7$s, %6$s</string>
<string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
<string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s %9$s, %1$s - %8$s %7$s y, %6$s</string>
<string name="short_format_month">%b</string>
- <string name="full_wday_month_day_no_year">E, d MMMM</string>
- <string name="abbrev_wday_month_day_year">d MMM y, E</string>
+ <string name="full_wday_month_day_no_year">d MMMM, EEEE</string>
+ <string name="abbrev_wday_month_day_year">d MMM yyyy, E</string>
</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index f434ce8..6f98e02 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -878,8 +878,8 @@
<item name="textColorSearchUrl">@android:color/search_url_text_holo</item>
<item name="textColorHighlight">@android:color/highlighted_text_holo_dark</item>
<item name="textColorHighlightInverse">@android:color/highlighted_text_holo_light</item>
- <item name="textColorLink">@android:color/link_text_holo_dark</item>
- <item name="textColorLinkInverse">@android:color/link_text_holo_light</item>
+ <item name="textColorLink">@android:color/holo_blue_light</item>
+ <item name="textColorLinkInverse">@android:color/holo_blue_light</item>
<item name="textColorAlertDialogListItem">@android:color/primary_text_holo_dark</item>
<item name="textAppearanceLarge">@android:style/TextAppearance.Holo.Large</item>
@@ -1182,8 +1182,8 @@
<item name="textColorSearchUrl">@android:color/search_url_text_holo</item>
<item name="textColorHighlight">@android:color/highlighted_text_holo_light</item>
<item name="textColorHighlightInverse">@android:color/highlighted_text_holo_dark</item>
- <item name="textColorLink">@android:color/link_text_holo_light</item>
- <item name="textColorLinkInverse">@android:color/link_text_holo_dark</item>
+ <item name="textColorLink">@android:color/holo_blue_light</item>
+ <item name="textColorLinkInverse">@android:color/holo_blue_light</item>
<item name="textColorAlertDialogListItem">@android:color/primary_text_holo_light</item>
<item name="textAppearanceLarge">@android:style/TextAppearance.Holo.Light.Large</item>
diff --git a/data/fonts/DroidSansFallback.ttf b/data/fonts/DroidSansFallback.ttf
index ba9d76f..ff97670 100644
--- a/data/fonts/DroidSansFallback.ttf
+++ b/data/fonts/DroidSansFallback.ttf
Binary files differ
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 392193b..5ccf87f 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -78,12 +78,8 @@
// conditionals don't get stripped... but that is probably what we want.
#if !LOG_NDEBUG
static const char *kReturnStrings[] = {
-#if 1 /* TODO: error update strings */
- "unknown",
-#else
+ "BR_ERROR",
"BR_OK",
- "BR_TIMEOUT",
- "BR_WAKEUP",
"BR_TRANSACTION",
"BR_REPLY",
"BR_ACQUIRE_RESULT",
@@ -94,25 +90,19 @@
"BR_RELEASE",
"BR_DECREFS",
"BR_ATTEMPT_ACQUIRE",
- "BR_EVENT_OCCURRED",
"BR_NOOP",
"BR_SPAWN_LOOPER",
"BR_FINISHED",
"BR_DEAD_BINDER",
- "BR_CLEAR_DEATH_NOTIFICATION_DONE"
-#endif
+ "BR_CLEAR_DEATH_NOTIFICATION_DONE",
+ "BR_FAILED_REPLY"
};
static const char *kCommandStrings[] = {
-#if 1 /* TODO: error update strings */
- "unknown",
-#else
- "BC_NOOP",
"BC_TRANSACTION",
"BC_REPLY",
"BC_ACQUIRE_RESULT",
"BC_FREE_BUFFER",
- "BC_TRANSACTION_COMPLETE",
"BC_INCREFS",
"BC_ACQUIRE",
"BC_RELEASE",
@@ -120,18 +110,12 @@
"BC_INCREFS_DONE",
"BC_ACQUIRE_DONE",
"BC_ATTEMPT_ACQUIRE",
- "BC_RETRIEVE_ROOT_OBJECT",
- "BC_SET_THREAD_ENTRY",
"BC_REGISTER_LOOPER",
"BC_ENTER_LOOPER",
"BC_EXIT_LOOPER",
- "BC_SYNC",
- "BC_STOP_PROCESS",
- "BC_STOP_SELF",
"BC_REQUEST_DEATH_NOTIFICATION",
"BC_CLEAR_DEATH_NOTIFICATION",
"BC_DEAD_BINDER_DONE"
-#endif
};
static const char* getReturnString(size_t idx)
@@ -154,30 +138,36 @@
{
const binder_transaction_data* btd =
(const binder_transaction_data*)data;
- out << "target=" << btd->target.ptr << " (cookie " << btd->cookie << ")" << endl
+ if (btd->target.handle < 1024) {
+ /* want to print descriptors in decimal; guess based on value */
+ out << "target.desc=" << btd->target.handle;
+ } else {
+ out << "target.ptr=" << btd->target.ptr;
+ }
+ out << " (cookie " << btd->cookie << ")" << endl
<< "code=" << TypeCode(btd->code) << ", flags=" << (void*)btd->flags << endl
<< "data=" << btd->data.ptr.buffer << " (" << (void*)btd->data_size
<< " bytes)" << endl
<< "offsets=" << btd->data.ptr.offsets << " (" << (void*)btd->offsets_size
- << " bytes)" << endl;
+ << " bytes)";
return btd+1;
}
static const void* printReturnCommand(TextOutput& out, const void* _cmd)
{
- static const int32_t N = sizeof(kReturnStrings)/sizeof(kReturnStrings[0]);
-
+ static const size_t N = sizeof(kReturnStrings)/sizeof(kReturnStrings[0]);
const int32_t* cmd = (const int32_t*)_cmd;
int32_t code = *cmd++;
- if (code == BR_ERROR) {
+ size_t cmdIndex = code & 0xff;
+ if (code == (int32_t) BR_ERROR) {
out << "BR_ERROR: " << (void*)(*cmd++) << endl;
return cmd;
- } else if (code < 0 || code >= N) {
+ } else if (cmdIndex >= N) {
out << "Unknown reply: " << code << endl;
return cmd;
}
+ out << kReturnStrings[cmdIndex];
- out << kReturnStrings[code];
switch (code) {
case BR_TRANSACTION:
case BR_REPLY: {
@@ -213,6 +203,11 @@
const int32_t c = *cmd++;
out << ": death cookie " << (void*)c;
} break;
+
+ default:
+ // no details to show for: BR_OK, BR_DEAD_REPLY,
+ // BR_TRANSACTION_COMPLETE, BR_FINISHED
+ break;
}
out << endl;
@@ -221,16 +216,17 @@
static const void* printCommand(TextOutput& out, const void* _cmd)
{
- static const int32_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[0]);
-
+ static const size_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[0]);
const int32_t* cmd = (const int32_t*)_cmd;
int32_t code = *cmd++;
- if (code < 0 || code >= N) {
+ size_t cmdIndex = code & 0xff;
+
+ if (cmdIndex >= N) {
out << "Unknown command: " << code << endl;
return cmd;
}
-
- out << kCommandStrings[code];
+ out << kCommandStrings[cmdIndex];
+
switch (code) {
case BC_TRANSACTION:
case BC_REPLY: {
@@ -254,7 +250,7 @@
case BC_RELEASE:
case BC_DECREFS: {
const int32_t d = *cmd++;
- out << ": descriptor=" << (void*)d;
+ out << ": desc=" << d;
} break;
case BC_INCREFS_DONE:
@@ -267,7 +263,7 @@
case BC_ATTEMPT_ACQUIRE: {
const int32_t p = *cmd++;
const int32_t d = *cmd++;
- out << ": decriptor=" << (void*)d << ", pri=" << p;
+ out << ": desc=" << d << ", pri=" << p;
} break;
case BC_REQUEST_DEATH_NOTIFICATION:
@@ -281,6 +277,11 @@
const int32_t c = *cmd++;
out << ": death cookie " << (void*)c;
} break;
+
+ default:
+ // no details to show for: BC_REGISTER_LOOPER, BC_ENTER_LOOPER,
+ // BC_EXIT_LOOPER
+ break;
}
out << endl;
@@ -592,6 +593,7 @@
status_t IPCThreadState::attemptIncStrongHandle(int32_t handle)
{
+ LOG_REMOTEREFS("IPCThreadState::attemptIncStrongHandle(%d)\n", handle);
mOut.writeInt32(BC_ATTEMPT_ACQUIRE);
mOut.writeInt32(0); // xxx was thread priority
mOut.writeInt32(handle);
@@ -772,7 +774,7 @@
} else {
bwr.read_size = 0;
}
-
+
IF_LOG_COMMANDS() {
TextOutput::Bundle _b(alog);
if (outAvail != 0) {
@@ -789,7 +791,7 @@
// Return immediately if there is nothing to do.
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
-
+
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
@@ -809,7 +811,7 @@
alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
}
} while (err == -EINTR);
-
+
IF_LOG_COMMANDS() {
alog << "Our err: " << (void*)err << ", write consumed: "
<< bwr.write_consumed << " (of " << mOut.dataSize()
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 7e8c7fd..349b9e3 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -91,6 +91,13 @@
#endif
}
+// TODO: This implementation is flawed and can generate T-junctions
+// in the mesh, which will in turn produce cracks when the
+// mesh is rotated/skewed. The easiest way to fix this would
+// be, for each row, to add new vertices shared with the previous
+// row when the two rows share an edge.
+// In practice, T-junctions do not appear often so this has yet
+// to be fixed.
void LayerRenderer::generateMesh() {
#if RENDER_LAYERS_AS_REGIONS
if (mLayer->region.isRect() || mLayer->region.isEmpty()) {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index a20a88e..32595e4 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -63,36 +63,42 @@
// In this array, the index of each Blender equals the value of the first
// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
static const Blender gBlends[] = {
- { SkXfermode::kClear_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
- { SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO },
- { SkXfermode::kDst_Mode, GL_ZERO, GL_ONE },
- { SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
- { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
- { SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO },
- { SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA },
- { SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
- { SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
- { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
- { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
- { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }
+ { SkXfermode::kClear_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
+ { SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO },
+ { SkXfermode::kDst_Mode, GL_ZERO, GL_ONE },
+ { SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
+ { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
+ { SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO },
+ { SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA },
+ { SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
+ { SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
+ { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
+ { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
+ { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
+ { SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
+ { SkXfermode::kMultiply_Mode, GL_ZERO, GL_SRC_COLOR },
+ { SkXfermode::kScreen_Mode, GL_ONE, GL_ONE_MINUS_SRC_COLOR }
};
// This array contains the swapped version of each SkXfermode. For instance
// this array's SrcOver blending mode is actually DstOver. You can refer to
// createLayer() for more information on the purpose of this array.
static const Blender gBlendsSwap[] = {
- { SkXfermode::kClear_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
- { SkXfermode::kSrc_Mode, GL_ZERO, GL_ONE },
- { SkXfermode::kDst_Mode, GL_ONE, GL_ZERO },
- { SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
- { SkXfermode::kDstOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
- { SkXfermode::kSrcIn_Mode, GL_ZERO, GL_SRC_ALPHA },
- { SkXfermode::kDstIn_Mode, GL_DST_ALPHA, GL_ZERO },
- { SkXfermode::kSrcOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
- { SkXfermode::kDstOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
- { SkXfermode::kSrcATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
- { SkXfermode::kDstATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
- { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }
+ { SkXfermode::kClear_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
+ { SkXfermode::kSrc_Mode, GL_ZERO, GL_ONE },
+ { SkXfermode::kDst_Mode, GL_ONE, GL_ZERO },
+ { SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
+ { SkXfermode::kDstOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
+ { SkXfermode::kSrcIn_Mode, GL_ZERO, GL_SRC_ALPHA },
+ { SkXfermode::kDstIn_Mode, GL_DST_ALPHA, GL_ZERO },
+ { SkXfermode::kSrcOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
+ { SkXfermode::kDstOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
+ { SkXfermode::kSrcATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
+ { SkXfermode::kDstATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
+ { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
+ { SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
+ { SkXfermode::kMultiply_Mode, GL_DST_COLOR, GL_ZERO },
+ { SkXfermode::kScreen_Mode, GL_ONE_MINUS_DST_COLOR, GL_ONE }
};
static const GLenum gTextureUnits[] = {
@@ -724,6 +730,8 @@
return;
}
+ // TODO: See LayerRenderer.cpp::generateMesh() for important
+ // information about this implementation
if (!layer->region.isEmpty()) {
size_t count;
const android::Rect* rects = layer->region.getArray(&count);
@@ -2487,7 +2495,7 @@
ProgramDescription& description, bool swapSrcDst) {
blend = blend || mode != SkXfermode::kSrcOver_Mode;
if (blend) {
- if (mode < SkXfermode::kPlus_Mode) {
+ if (mode <= SkXfermode::kScreen_Mode) {
if (!mCaches.blend) {
glEnable(GL_BLEND);
}
@@ -2540,15 +2548,7 @@
void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
if (paint) {
- if (!mCaches.extensions.hasFramebufferFetch()) {
- const bool isMode = SkXfermode::IsMode(paint->getXfermode(), mode);
- if (!isMode) {
- // Assume SRC_OVER
- *mode = SkXfermode::kSrcOver_Mode;
- }
- } else {
- *mode = getXfermode(paint->getXfermode());
- }
+ *mode = getXfermode(paint->getXfermode());
// Skia draws using the color's alpha channel if < 255
// Otherwise, it uses the paint's alpha
diff --git a/libs/utils/Static.cpp b/libs/utils/Static.cpp
index 4dfa578..ceca435 100644
--- a/libs/utils/Static.cpp
+++ b/libs/utils/Static.cpp
@@ -56,7 +56,9 @@
protected:
virtual status_t writeLines(const struct iovec& vec, size_t N)
{
- android_writevLog(&vec, N);
+ //android_writevLog(&vec, N); <-- this is now a no-op
+ if (N != 1) LOGI("WARNING: writeLines N=%d\n", N);
+ LOGI("%.*s", vec.iov_len, (const char*) vec.iov_base);
return NO_ERROR;
}
};
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index aa0a2e9..d7b8eaa 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -3758,65 +3758,33 @@
/**
* This method extracts a frame from the input file
- * and returns the frame as a bitmap
- *
- * @param inputFile The inputFile
- * @param width The width of the output frame
- * @param height The height of the output frame
- * @param timeMS The time in ms at which the frame has to be extracted
+ * and returns the frame as a bitmap. See getPixelsList() for more information.
*/
- Bitmap getPixels(String inputFile, int width, int height, long timeMS) {
- if (inputFile == null) {
- throw new IllegalArgumentException("Invalid input file");
- }
-
- /* Make width and height as even */
- final int newWidth = (width + 1) & 0xFFFFFFFE;
- final int newHeight = (height + 1) & 0xFFFFFFFE;
-
- /* Create a temp bitmap for resized thumbnails */
- Bitmap tempBitmap = null;
- if ((newWidth != width) || (newHeight != height)) {
- tempBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
- }
-
- IntBuffer rgb888 = IntBuffer.allocate(newWidth * newHeight * 4);
- Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- nativeGetPixels(inputFile, rgb888.array(), newWidth, newHeight, timeMS);
-
- if ((newWidth == width) && (newHeight == height)) {
- bitmap.copyPixelsFromBuffer(rgb888);
- } else {
- /* Create a temp bitmap to be used for resize */
- tempBitmap.copyPixelsFromBuffer(rgb888);
-
- /* Create a canvas to resize */
- final Canvas canvas = new Canvas(bitmap);
- canvas.drawBitmap(tempBitmap, new Rect(0, 0, newWidth, newHeight),
- new Rect(0, 0, width, height), sResizePaint);
- canvas.setBitmap(null);
- }
-
- if (tempBitmap != null) {
- tempBitmap.recycle();
- }
-
- return bitmap;
+ Bitmap getPixels(String filename, int width, int height, long timeMs,
+ int videoRotation) {
+ final Bitmap result[] = new Bitmap[1];
+ getPixelsList(filename, width, height, timeMs, timeMs, 1, new int[] {0},
+ new MediaItem.GetThumbnailListCallback() {
+ public void onThumbnail(Bitmap bitmap, int index) {
+ result[0] = bitmap;
+ }
+ }, videoRotation);
+ return result[0];
}
/**
* This method extracts a list of frame from the
* input file and returns the frame in bitmap array
*
- * @param filename The inputFile
- * @param width The width of the output frame
- * @param height The height of the output frame
+ * @param filename The input file name
+ * @param width The width of the output frame, before rotation
+ * @param height The height of the output frame, before rotation
* @param startMs The starting time in ms
* @param endMs The end time in ms
* @param thumbnailCount The number of frames to be extracted
* @param indices The indices of thumbnails wanted
* @param callback The callback used to pass back the bitmaps
- * from startMs to endMs
+ * @param videoRotation The rotation degree need to be done for the bitmap
*
* @return The frames as bitmaps in bitmap array
**/
@@ -3824,62 +3792,69 @@
long startMs, long endMs, int thumbnailCount, int[] indices,
final MediaItem.GetThumbnailListCallback callback,
final int videoRotation) {
- /* Make width and height as even */
- final int newWidth = (width + 1) & 0xFFFFFFFE;
- final int newHeight = (height + 1) & 0xFFFFFFFE;
- final int thumbnailSize = newWidth * newHeight;
- /* Create a temp bitmap for resized thumbnails */
- final Bitmap tempBitmap =
- (newWidth != width || newHeight != height)
- ? Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888)
+ // The decoder needs output width and height as even
+ final int decWidth = (width + 1) & 0xFFFFFFFE;
+ final int decHeight = (height + 1) & 0xFFFFFFFE;
+ final int thumbnailSize = decWidth * decHeight;
+
+ // We convert the decoder output (in int[]) to a bitmap by first
+ // copy it into an IntBuffer, then use Bitmap.copyPixelsFromBuffer to
+ // copy it to the bitmap.
+ final int[] decArray = new int[thumbnailSize];
+ final IntBuffer decBuffer = IntBuffer.allocate(thumbnailSize);
+
+ // If we need to resize and/or rotate the decoder output, we need a
+ // temporary bitmap to hold the decoded output.
+ final boolean needToMassage =
+ (decWidth != width || decHeight != height || videoRotation != 0);
+ final Bitmap tmpBitmap = needToMassage
+ ? Bitmap.createBitmap(decWidth, decHeight, Bitmap.Config.ARGB_8888)
: null;
- final int[] rgb888 = new int[thumbnailSize];
- final IntBuffer tmpBuffer = IntBuffer.allocate(thumbnailSize);
- nativeGetPixelsList(filename, rgb888, newWidth, newHeight,
- thumbnailCount, videoRotation, startMs, endMs, indices,
+ // The final output bitmap width/height may swap because of rotation.
+ final boolean needToSwapWH = (videoRotation == 90 || videoRotation == 270);
+ final int outWidth = needToSwapWH ? height : width;
+ final int outHeight = needToSwapWH ? width : height;
+
+ nativeGetPixelsList(filename, decArray, decWidth, decHeight,
+ thumbnailCount, startMs, endMs, indices,
new NativeGetPixelsListCallback() {
public void onThumbnail(int index) {
- Bitmap bitmap = Bitmap.createBitmap(
- width, height, Bitmap.Config.ARGB_8888);
- tmpBuffer.put(rgb888, 0, thumbnailSize);
- tmpBuffer.rewind();
+ // This is the bitmap we will output to the client
+ Bitmap outBitmap = Bitmap.createBitmap(
+ outWidth, outHeight, Bitmap.Config.ARGB_8888);
- if ((newWidth == width) && (newHeight == height)) {
- bitmap.copyPixelsFromBuffer(tmpBuffer);
+ // Copy int[] to IntBuffer
+ decBuffer.put(decArray, 0, thumbnailSize);
+ decBuffer.rewind();
+
+ if (!needToMassage) {
+ // We can directly read the decoded result to output bitmap
+ outBitmap.copyPixelsFromBuffer(decBuffer);
} else {
- /* Copy the out rgb buffer to temp bitmap */
- tempBitmap.copyPixelsFromBuffer(tmpBuffer);
+ // Copy the decoded result to an intermediate bitmap first
+ tmpBitmap.copyPixelsFromBuffer(decBuffer);
- /* Create a canvas to resize */
- final Canvas canvas = new Canvas(bitmap);
- canvas.drawBitmap(tempBitmap,
- new Rect(0, 0, newWidth, newHeight),
- new Rect(0, 0, width, height), sResizePaint);
-
- canvas.setBitmap(null);
+ // Create a canvas to resize/rotate the bitmap
+ // First scale the decoded bitmap to (0,0)-(1,1), rotate it
+ // with (0.5, 0.5) as center, then scale it to
+ // (outWidth, outHeight).
+ final Canvas canvas = new Canvas(outBitmap);
+ Matrix m = new Matrix();
+ float sx = 1f / decWidth;
+ float sy = 1f / decHeight;
+ m.postScale(sx, sy);
+ m.postRotate(videoRotation, 0.5f, 0.5f);
+ m.postScale(outWidth, outHeight);
+ canvas.drawBitmap(tmpBitmap, m, sResizePaint);
}
-
- if (videoRotation == 0) {
- callback.onThumbnail(bitmap, index);
- } else {
- Matrix mtx = new Matrix();
- mtx.postRotate(videoRotation);
- Bitmap rotatedBmp =
- Bitmap.createBitmap(bitmap, 0, 0, width, height, mtx, false);
- callback.onThumbnail(rotatedBmp, index);
-
- if (bitmap != null) {
- bitmap.recycle();
- }
- }
-
+ callback.onThumbnail(outBitmap, index);
}
});
- if (tempBitmap != null) {
- tempBitmap.recycle();
+ if (tmpBitmap != null) {
+ tmpBitmap.recycle();
}
}
@@ -3996,7 +3971,7 @@
long timeMS);
private native int nativeGetPixelsList(String fileName, int[] pixelArray,
- int width, int height, int nosofTN, int videoRotation, long startTimeMs,
+ int width, int height, int nosofTN, long startTimeMs,
long endTimeMs, int[] indices, NativeGetPixelsListCallback callback);
/**
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index 65a9e19..a862d00 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -606,7 +606,7 @@
public Bitmap getThumbnail(int width, int height, long timeMs) throws IOException {
if (getGeneratedImageClip() != null) {
return mMANativeHelper.getPixels(getGeneratedImageClip(),
- width, height,timeMs);
+ width, height, timeMs, 0);
} else {
return scaleImage(mFilename, width, height);
}
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index 2ce857c..bbcdf57 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -293,7 +293,14 @@
throw new IllegalArgumentException("Invalid Dimensions");
}
- return mMANativeHelper.getPixels(super.getFilename(), width, height,timeMs);
+ if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
+ int temp = width;
+ width = height;
+ height = temp;
+ }
+
+ return mMANativeHelper.getPixels(
+ getFilename(), width, height, timeMs, mVideoRotationDegree);
}
/*
@@ -318,8 +325,14 @@
throw new IllegalArgumentException("Invalid dimension");
}
- mMANativeHelper.getPixelsList(super.getFilename(), width,
- height, startMs, endMs, thumbnailCount, indices, callback,
+ if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
+ int temp = width;
+ width = height;
+ height = temp;
+ }
+
+ mMANativeHelper.getPixelsList(getFilename(), width, height,
+ startMs, endMs, thumbnailCount, indices, callback,
mVideoRotationDegree);
}
diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java
index f18dd88..2446c2f 100755
--- a/media/java/android/media/videoeditor/VideoEditorImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorImpl.java
@@ -1825,27 +1825,10 @@
if (mMediaItems.size() > 0) {
MediaItem mI = mMediaItems.get(0);
/*
- * Lets initialize the width for default aspect ratio i.e 16:9
+ * Keep aspect ratio of the image
*/
int height = 480;
- int width = 854;
- switch (mI.getAspectRatio()) {
- case MediaProperties.ASPECT_RATIO_3_2:
- width = 720;
- break;
- case MediaProperties.ASPECT_RATIO_4_3:
- width = 640;
- break;
- case MediaProperties.ASPECT_RATIO_5_3:
- width = 800;
- break;
- case MediaProperties.ASPECT_RATIO_11_9:
- width = 586;
- break;
- case MediaProperties.ASPECT_RATIO_16_9:
- case MediaProperties.ASPECT_RATIO_UNDEFINED:
- break;
- }
+ int width = mI.getWidth() * height / mI.getHeight();
Bitmap projectBitmap = null;
String filename = mI.getFilename();
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index 4e73581..4e954fc 100755
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -185,7 +185,6 @@
M4OSA_UInt32 width,
M4OSA_UInt32 height,
M4OSA_UInt32 noOfThumbnails,
- M4OSA_UInt32 videoRotation,
jlong startTime,
jlong endTime,
jintArray indexArray,
@@ -292,7 +291,7 @@
(void *)videoEditor_release },
{"nativeGetPixels", "(Ljava/lang/String;[IIIJ)I",
(void*)videoEditor_getPixels },
- {"nativeGetPixelsList", "(Ljava/lang/String;[IIIIIJJ[ILandroid/media/videoeditor/MediaArtistNativeHelper$NativeGetPixelsListCallback;)I",
+ {"nativeGetPixelsList", "(Ljava/lang/String;[IIIIJJ[ILandroid/media/videoeditor/MediaArtistNativeHelper$NativeGetPixelsListCallback;)I",
(void*)videoEditor_getPixelsList },
{"getMediaProperties",
"(Ljava/lang/String;)Landroid/media/videoeditor/MediaArtistNativeHelper$Properties;",
@@ -2286,7 +2285,6 @@
M4OSA_UInt32 width,
M4OSA_UInt32 height,
M4OSA_UInt32 noOfThumbnails,
- M4OSA_UInt32 videoRotation,
jlong startTime,
jlong endTime,
jintArray indexArray,
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 7509239..c2c6715 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1078,6 +1078,11 @@
frames = mRemainingFrames;
}
+ int32_t waitCount = -1;
+ if (mUpdatePeriod || (!mMarkerReached && mMarkerPosition) || mLoopCount) {
+ waitCount = 1;
+ }
+
do {
audioBuffer.frameCount = frames;
@@ -1085,7 +1090,7 @@
// Calling obtainBuffer() with a wait count of 1
// limits wait time to WAIT_PERIOD_MS. This prevents from being
// stuck here not being able to handle timed events (position, markers, loops).
- status_t err = obtainBuffer(&audioBuffer, 1);
+ status_t err = obtainBuffer(&audioBuffer, waitCount);
if (err < NO_ERROR) {
if (err != TIMED_OUT) {
LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index d41ab1b..ba076f5 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -20,8 +20,8 @@
#include <binder/IPCThreadState.h>
#include <media/AudioTrack.h>
+#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/AudioPlayer.h>
-#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaSource.h>
@@ -60,7 +60,7 @@
}
void AudioPlayer::setSource(const sp<MediaSource> &source) {
- CHECK_EQ(mSource, NULL);
+ CHECK(mSource == NULL);
mSource = source;
}
@@ -466,6 +466,8 @@
}
int64_t AudioPlayer::getRealTimeUsLocked() const {
+ CHECK(mStarted);
+ CHECK_NE(mSampleRate, 0);
return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
}
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 47224cc..07a46bd 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1736,7 +1736,9 @@
modifyFlags(TEXT_RUNNING, SET);
}
- TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
+ TimeSource *ts =
+ ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
+ ? &mSystemTimeSource : mTimeSource;
if (mFlags & FIRST_FRAME) {
modifyFlags(FIRST_FRAME, CLEAR);
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 50dd804..306f1f6 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// #define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#define LOG_TAG "SurfaceMediaSource"
#include <media/stagefright/SurfaceMediaSource.h>
@@ -458,6 +458,10 @@
LOGV("queueBuffer");
Mutex::Autolock lock(mMutex);
+ *outWidth = mDefaultWidth;
+ *outHeight = mDefaultHeight;
+ *outTransform = 0;
+
if (bufIndex < 0 || bufIndex >= mBufferCount) {
LOGE("queueBuffer: slot index out of range [0, %d]: %d",
mBufferCount, bufIndex);
@@ -518,9 +522,6 @@
// buffer is available
onFrameReceivedLocked();
- *outWidth = mDefaultWidth;
- *outHeight = mDefaultHeight;
- *outTransform = 0;
return OK;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 43905dd..10e7602 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -96,11 +96,13 @@
/* package */ final class ActivityDescription {
final ActivityManager.RecentTaskInfo recentTaskInfo;
final ResolveInfo resolveInfo;
- int taskId; // application task id for curating apps
- Intent intent; // launch intent for application
+ final int taskId; // application task id for curating apps
+ final int persistentTaskId; // persistent id
+ final Intent intent; // launch intent for application
+ final String packageName; // used to override animations (see onClick())
+ final int position; // position in list
+
Matrix matrix; // arbitrary rotation matrix to correct orientation
- String packageName; // used to override animations (see onClick())
- int position; // position in list
private Bitmap mThumbnail; // generated by Activity.onCreateThumbnail()
private Drawable mIcon; // application package icon
@@ -108,11 +110,12 @@
public ActivityDescription(ActivityManager.RecentTaskInfo _recentInfo,
ResolveInfo _resolveInfo, Intent _intent,
- int _id, int _pos, String _packageName) {
+ int _pos, String _packageName) {
recentTaskInfo = _recentInfo;
resolveInfo = _resolveInfo;
intent = _intent;
- taskId = _id;
+ taskId = _recentInfo.id;
+ persistentTaskId = _recentInfo.persistentId;
position = _pos;
packageName = _packageName;
}
@@ -496,17 +499,17 @@
final String title = info.loadLabel(pm).toString();
// Drawable icon = info.loadIcon(pm);
Drawable icon = getFullResIcon(resolveInfo, pm);
- int id = recentInfo.id;
if (title != null && title.length() > 0 && icon != null) {
- if (DEBUG) Log.v(TAG, "creating activity desc for id=" + id + ", label=" + title);
+ if (DEBUG) Log.v(TAG, "creating activity desc for id="
+ + recentInfo.id + ", label=" + title);
ActivityManager.TaskThumbnails thumbs = am.getTaskThumbnails(
recentInfo.persistentId);
ActivityDescription item = new ActivityDescription(recentInfo,
- resolveInfo, intent, id, index, info.packageName);
+ resolveInfo, intent, index, info.packageName);
activityDescriptions.add(item);
++index;
} else {
- if (DEBUG) Log.v(TAG, "SKIPPING item " + id);
+ if (DEBUG) Log.v(TAG, "SKIPPING item " + recentInfo.id);
}
}
}
@@ -727,7 +730,7 @@
// the task.
final ActivityManager am = (ActivityManager)
mContext.getSystemService(Context.ACTIVITY_SERVICE);
- am.removeTask(ad.taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+ am.removeTask(ad.persistentTaskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
}
private void startApplicationDetailsActivity(String packageName) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 6ec3443..55623f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1174,7 +1174,6 @@
case MSG_OPEN_RECENTS_PANEL:
if (DEBUG) Slog.d(TAG, "opening recents panel");
if (mRecentsPanel != null) {
- disable(StatusBarManager.DISABLE_BACK);
mRecentsPanel.setVisibility(View.VISIBLE);
mRecentsPanel.show(true, true);
}
@@ -1182,7 +1181,6 @@
case MSG_CLOSE_RECENTS_PANEL:
if (DEBUG) Slog.d(TAG, "closing recents panel");
if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
- disable(StatusBarManager.DISABLE_NONE);
mRecentsPanel.show(false, true);
}
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index d3f9525..c19550b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -22,11 +22,9 @@
import android.content.IntentFilter;
import android.text.format.DateFormat;
import android.util.AttributeSet;
-import android.util.Slog;
-import android.widget.TextView;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewParent;
+import android.widget.TextView;
import com.android.systemui.R;
@@ -42,9 +40,10 @@
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(Intent.ACTION_TIME_TICK)
- || action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_TIME_TICK.equals(action)
+ || Intent.ACTION_TIME_CHANGED.equals(action)
+ || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
updateClock();
}
}
@@ -118,6 +117,7 @@
// Register for Intent broadcasts for the clock and battery
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
+ filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
mContext.registerReceiver(mIntentReceiver, filter, null, null);
updateClock();
@@ -127,4 +127,3 @@
}
}
}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index e287b7a..06798c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -20,7 +20,7 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
-import android.animation.TimeAnimator;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
@@ -37,12 +37,12 @@
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
-import java.util.HashSet;
+import java.util.HashMap;
public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Callback {
private static final String TAG = "NotificationRowLayout";
private static final boolean DEBUG = false;
- private static final boolean SLOW_ANIMATIONS = false; // DEBUG;
+ private static final boolean SLOW_ANIMATIONS = DEBUG;
private static final boolean ANIMATE_LAYOUT = true;
@@ -54,8 +54,8 @@
int mRowHeight = 0;
int mHeight = 0;
- HashSet<View> mAppearingViews = new HashSet<View>();
- HashSet<View> mDisappearingViews = new HashSet<View>();
+ HashMap<View, ValueAnimator> mAppearingViews = new HashMap<View, ValueAnimator>();
+ HashMap<View, ValueAnimator> mDisappearingViews = new HashMap<View, ValueAnimator>();
private SwipeHelper mSwipeHelper;
@@ -166,8 +166,6 @@
final View childF = child;
if (ANIMATE_LAYOUT) {
- mAppearingViews.add(child);
-
child.setPivotY(0);
final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f);
alphaFade.setDuration(APPEAR_ANIM_LEN);
@@ -178,7 +176,11 @@
requestLayout(); // pick up any final changes in position
}
});
+
alphaFade.start();
+
+ mAppearingViews.put(child, alphaFade);
+
requestLayout(); // start the container animation
}
}
@@ -187,27 +189,27 @@
public void removeView(View child) {
final View childF = child;
if (ANIMATE_LAYOUT) {
- if (mAppearingViews.contains(child)) {
+ if (mAppearingViews.containsKey(child)) {
mAppearingViews.remove(child);
}
- mDisappearingViews.add(child);
-
child.setPivotY(0);
final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f);
+ alphaFade.setDuration(DISAPPEAR_ANIM_LEN);
alphaFade.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (DEBUG) Slog.d(TAG, "actually removing child: " + childF);
NotificationRowLayout.super.removeView(childF);
- childF.setAlpha(1f);
mDisappearingViews.remove(childF);
requestLayout(); // pick up any final changes in position
}
});
- alphaFade.setDuration(DISAPPEAR_ANIM_LEN);
alphaFade.start();
+
+ mDisappearingViews.put(child, alphaFade);
+
requestLayout(); // start the container animation
} else {
super.removeView(child);
@@ -246,7 +248,7 @@
if (child.getVisibility() == GONE) {
continue;
}
- if (mDisappearingViews.contains(child)) {
+ if (mDisappearingViews.containsKey(child)) {
continue;
}
numRows++;
@@ -304,14 +306,19 @@
if (child.getVisibility() == GONE) {
continue;
}
- float alpha = child.getAlpha();
- if (alpha > 1.0f) {
- if (DEBUG) {
- Slog.w(TAG, "alpha=" + alpha + " > 1!!! " + child);
- }
- alpha = 1f;
+ float progress = 1.0f;
+ if (mDisappearingViews.containsKey(child)) {
+ progress = 1.0f - mDisappearingViews.get(child).getAnimatedFraction();
+ } else if (mAppearingViews.containsKey(child)) {
+ progress = 1.0f - mAppearingViews.get(child).getAnimatedFraction();
}
- final int thisRowHeight = (int)(alpha * mRowHeight);
+ if (progress > 1.0f) {
+ if (DEBUG) {
+ Slog.w(TAG, "progress=" + progress + " > 1!!! " + child);
+ }
+ progress = 1f;
+ }
+ final int thisRowHeight = (int)(progress * mRowHeight);
if (DEBUG) {
Slog.d(TAG, String.format(
"laying out child #%d: (0, %d, %d, %d) h=%d",
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index b4c480b..39011d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -301,6 +301,7 @@
mRecentsPanel = (RecentsPanelView) View.inflate(context,
R.layout.status_bar_recent_panel, null);
mRecentsPanel.setVisibility(View.GONE);
+ mRecentsPanel.setSystemUiVisibility(View.STATUS_BAR_DISABLE_BACK);
mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL,
mRecentsPanel));
mStatusBarView.setIgnoreChildren(2, mRecentButton, mRecentsPanel);
@@ -436,6 +437,13 @@
sb.setHandler(mHandler);
+ // Sanity-check that someone hasn't set up the config wrong and asked for a navigation bar
+ // on a tablet that has only the system bar
+ if (mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_showNavigationBar)) {
+ throw new RuntimeException("Tablet device cannot show navigation bar and system bar");
+ }
+
mBarContents = (ViewGroup) sb.findViewById(R.id.bar_contents);
// layout transitions for the status bar's contents
mBarContentsLayoutTransition = new LayoutTransition();
@@ -705,7 +713,6 @@
case MSG_OPEN_RECENTS_PANEL:
if (DEBUG) Slog.d(TAG, "opening recents panel");
if (mRecentsPanel != null) {
- disable(StatusBarManager.DISABLE_BACK);
mRecentsPanel.setVisibility(View.VISIBLE);
mRecentsPanel.show(true, true);
}
@@ -713,7 +720,6 @@
case MSG_CLOSE_RECENTS_PANEL:
if (DEBUG) Slog.d(TAG, "closing recents panel");
if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
- disable(StatusBarManager.DISABLE_NONE);
mRecentsPanel.show(false, true);
}
break;
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 2a34f18..64a9677 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -1202,12 +1202,15 @@
// showing secure lockscreen; disable expanding.
flags |= StatusBarManager.DISABLE_EXPAND;
}
+ if (isSecure()) {
+ // showing secure lockscreen; disable ticker.
+ flags |= StatusBarManager.DISABLE_NOTIFICATION_TICKER;
+ }
}
if (DEBUG) {
- Log.d(TAG,
- "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
- + " isSecure=" + isSecure() + " --> flags=" + flags);
+ Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
+ + " isSecure=" + isSecure() + " --> flags=0x" + Integer.toHexString(flags));
}
mStatusBarManager.disable(flags);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index b69a7c2..f5e3a45 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -384,7 +384,7 @@
st.menu.stopDispatchingItemsChanged();
if ((cb == null) || !cb.onCreatePanelMenu(st.featureId, st.menu)) {
// Ditch the menu created above
- st.menu = null;
+ st.setMenu(null);
if (mActionBar != null) {
// Don't show it in the action bar either
@@ -3207,7 +3207,17 @@
}
void setMenu(MenuBuilder menu) {
+ if (menu == this.menu) return;
+
+ if (this.menu != null) {
+ this.menu.removeMenuPresenter(iconMenuPresenter);
+ this.menu.removeMenuPresenter(listMenuPresenter);
+ }
this.menu = menu;
+ if (menu != null) {
+ if (iconMenuPresenter != null) menu.addMenuPresenter(iconMenuPresenter);
+ if (listMenuPresenter != null) menu.addMenuPresenter(listMenuPresenter);
+ }
}
MenuView getListMenuView(MenuPresenter.Callback cb) {
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 1497511..349b4d2 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -98,6 +98,7 @@
public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
/** {@link #mStatsXtUid} headers. */
+ private static final String KEY_IDX = "idx";
private static final String KEY_IFACE = "iface";
private static final String KEY_UID = "uid_tag_int";
private static final String KEY_COUNTER_SET = "cnt_set";
@@ -1323,18 +1324,22 @@
// TODO: remove knownLines check once 5087722 verified
final HashSet<String> knownLines = Sets.newHashSet();
+ // TODO: remove lastIdx check once 5270106 verified
+ int lastIdx;
final ArrayList<String> keys = Lists.newArrayList();
final ArrayList<String> values = Lists.newArrayList();
final HashMap<String, String> parsed = Maps.newHashMap();
BufferedReader reader = null;
+ String line = null;
try {
reader = new BufferedReader(new FileReader(mStatsXtUid));
// parse first line as header
- String line = reader.readLine();
+ line = reader.readLine();
splitLine(line, keys);
+ lastIdx = 1;
// parse remaining lines
while ((line = reader.readLine()) != null) {
@@ -1342,32 +1347,35 @@
parseLine(keys, values, parsed);
if (!knownLines.add(line)) {
- throw new IllegalStateException("encountered duplicate proc entry");
+ throw new IllegalStateException("duplicate proc entry: " + line);
}
- try {
- entry.iface = parsed.get(KEY_IFACE);
- entry.uid = getParsedInt(parsed, KEY_UID);
- entry.set = getParsedInt(parsed, KEY_COUNTER_SET);
- entry.tag = kernelToTag(parsed.get(KEY_TAG_HEX));
- 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);
+ final int idx = getParsedInt(parsed, KEY_IDX);
+ if (idx != lastIdx + 1) {
+ throw new IllegalStateException(
+ "inconsistent idx=" + idx + " after lastIdx=" + lastIdx);
+ }
+ lastIdx = idx;
- if (limitUid == UID_ALL || limitUid == entry.uid) {
- stats.addValues(entry);
- }
- } catch (NumberFormatException e) {
- Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
+ entry.iface = parsed.get(KEY_IFACE);
+ entry.uid = getParsedInt(parsed, KEY_UID);
+ entry.set = getParsedInt(parsed, KEY_COUNTER_SET);
+ entry.tag = kernelToTag(parsed.get(KEY_TAG_HEX));
+ 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);
+
+ if (limitUid == UID_ALL || limitUid == entry.uid) {
+ stats.addValues(entry);
}
}
} catch (NullPointerException e) {
- throw new IllegalStateException("problem parsing stats: " + e);
+ throw new IllegalStateException("problem parsing line: " + line, e);
} catch (NumberFormatException e) {
- throw new IllegalStateException("problem parsing stats: " + e);
+ throw new IllegalStateException("problem parsing line: " + line, e);
} catch (IOException e) {
- throw new IllegalStateException("problem parsing stats: " + e);
+ throw new IllegalStateException("problem parsing line: " + line, e);
} finally {
IoUtils.closeQuietly(reader);
}
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index ca3b12d..bab9f8a 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -301,7 +301,7 @@
// also allows calls from window manager which is in this process.
enforceStatusBarService();
- if (SPEW) Slog.d(TAG, "setSystemUiVisibility(" + vis + ")");
+ if (SPEW) Slog.d(TAG, "setSystemUiVisibility(0x" + Integer.toHexString(vis) + ")");
synchronized (mLock) {
updateUiVisibilityLocked(vis);
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index 4447ad0..bc256ed 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -383,7 +383,7 @@
public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
String reason, String apn, String apnType, LinkProperties linkProperties,
- LinkCapabilities linkCapabilities, int networkType) {
+ LinkCapabilities linkCapabilities, int networkType, boolean roaming) {
if (!checkNotifyPermission("notifyDataConnection()" )) {
return;
}
@@ -437,7 +437,7 @@
}
}
broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
- apnType, linkProperties, linkCapabilities);
+ apnType, linkProperties, linkCapabilities, roaming);
}
public void notifyDataConnectionFailed(String reason, String apnType) {
@@ -596,7 +596,7 @@
private void broadcastDataConnectionStateChanged(int state,
boolean isDataConnectivityPossible,
String reason, String apn, String apnType, LinkProperties linkProperties,
- LinkCapabilities linkCapabilities) {
+ LinkCapabilities linkCapabilities, boolean roaming) {
// Note: not reporting to the battery stats service here, because the
// status bar takes care of that after taking into account all of the
// required info.
@@ -618,6 +618,8 @@
if (linkCapabilities != null) {
intent.putExtra(Phone.DATA_LINK_CAPABILITIES_KEY, linkCapabilities);
}
+ if (roaming) intent.putExtra(Phone.DATA_NETWORK_ROAMING_KEY, true);
+
intent.putExtra(Phone.DATA_APN_KEY, apn);
intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
mContext.sendStickyBroadcast(intent);
diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java
index e45c368..6a63eac 100644
--- a/services/java/com/android/server/WiredAccessoryObserver.java
+++ b/services/java/com/android/server/WiredAccessoryObserver.java
@@ -107,25 +107,18 @@
private synchronized final void updateState(String name, int state)
{
if (name.equals("usb_audio")) {
- if (state == 1) {
- switchState = ((mHeadsetState & (BIT_HEADSET|BIT_HEADSET_NO_MIC|
- BIT_USB_HEADSET_DGTL|BIT_HDMI_AUDIO)) |
- (state << 2));
- } else if (state == 2) {
- switchState = ((mHeadsetState & (BIT_HEADSET|BIT_HEADSET_NO_MIC|
- BIT_USB_HEADSET_ANLG|BIT_HDMI_AUDIO)) |
- (state << 3));
- } else switchState = (mHeadsetState & (BIT_HEADSET|BIT_HEADSET_NO_MIC|BIT_HDMI_AUDIO));
- }
- else if (name.equals("hdmi")) {
+ switchState = ((mHeadsetState & (BIT_HEADSET|BIT_HEADSET_NO_MIC|BIT_HDMI_AUDIO)) |
+ ((state == 1) ? BIT_USB_HEADSET_ANLG :
+ ((state == 2) ? BIT_USB_HEADSET_DGTL : 0)));
+ } else if (name.equals("hdmi")) {
switchState = ((mHeadsetState & (BIT_HEADSET|BIT_HEADSET_NO_MIC|
BIT_USB_HEADSET_DGTL|BIT_USB_HEADSET_ANLG)) |
- (state << 4));
- }
- else {
+ ((state == 1) ? BIT_HDMI_AUDIO : 0));
+ } else {
switchState = ((mHeadsetState & (BIT_HDMI_AUDIO|BIT_USB_HEADSET_ANLG|
BIT_USB_HEADSET_DGTL)) |
- state);
+ ((state == 1) ? BIT_HEADSET :
+ ((state == 2) ? BIT_HEADSET_NO_MIC : 0)));
}
update(name, switchState);
}
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index eb399ad..aa43bb6 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -203,6 +203,7 @@
}
case 1: {
mSendHoverDelayed.remove();
+ mPerformLongPressDelayed.remove();
// Send a hover for every finger down so the user gets feedback.
final int pointerId = pointerTracker.getPrimaryActivePointerId();
final int pointerIdBits = (1 << pointerId);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 9db56ce..d6d3b9d 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -106,6 +106,7 @@
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.EventLog;
+import android.util.Pair;
import android.util.Slog;
import android.util.Log;
import android.util.PrintWriterPrinter;
@@ -5004,7 +5005,13 @@
maxNum < N ? maxNum : N);
for (int i=0; i<N && maxNum > 0; i++) {
TaskRecord tr = mRecentTasks.get(i);
- if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
+ // Return the entry if desired by the caller. We always return
+ // the first entry, because callers always expect this to be the
+ // forground app. We may filter others if the caller has
+ // not supplied RECENT_WITH_EXCLUDED and there is some reason
+ // we should exclude the entry.
+ if (i == 0
+ || ((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
|| (tr.intent == null)
|| ((tr.intent.getFlags()
&Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
@@ -5152,6 +5159,29 @@
cleanUpRemovedTaskLocked(r,
(flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
return true;
+ } else {
+ TaskRecord tr = null;
+ int i=0;
+ while (i < mRecentTasks.size()) {
+ TaskRecord t = mRecentTasks.get(i);
+ if (t.taskId == taskId) {
+ tr = t;
+ break;
+ }
+ i++;
+ }
+ if (tr != null) {
+ if (tr.numActivities <= 0) {
+ // Caller is just removing a recent task that is
+ // not actively running. That is easy!
+ mRecentTasks.remove(i);
+ } else {
+ Slog.w(TAG, "removeTask: task " + taskId
+ + " does not have activities to remove, "
+ + " but numActivities=" + tr.numActivities
+ + ": " + tr);
+ }
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -7546,7 +7576,33 @@
return errList;
}
-
+
+ static int oomAdjToImportance(int adj, ActivityManager.RunningAppProcessInfo currApp) {
+ if (adj >= ProcessList.EMPTY_APP_ADJ) {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
+ } else if (adj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
+ if (currApp != null) {
+ currApp.lru = adj - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
+ }
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
+ } else if (adj >= ProcessList.HOME_APP_ADJ) {
+ if (currApp != null) {
+ currApp.lru = 0;
+ }
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
+ } else if (adj >= ProcessList.SECONDARY_SERVER_ADJ) {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
+ } else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
+ } else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
+ } else if (adj >= ProcessList.VISIBLE_APP_ADJ) {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
+ } else {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+ }
+ }
+
public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
// Lazy instantiation of list
List<ActivityManager.RunningAppProcessInfo> runList = null;
@@ -7567,28 +7623,12 @@
currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
}
int adj = app.curAdj;
- if (adj >= ProcessList.EMPTY_APP_ADJ) {
- currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
- } else if (adj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
- currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
- currApp.lru = adj - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
- } else if (adj >= ProcessList.HOME_APP_ADJ) {
- currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
- currApp.lru = 0;
- } else if (adj >= ProcessList.SECONDARY_SERVER_ADJ) {
- currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
- } else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
- currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
- } else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
- currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
- } else if (adj >= ProcessList.VISIBLE_APP_ADJ) {
- currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
- } else {
- currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
- }
+ currApp.importance = oomAdjToImportance(adj, currApp);
currApp.importanceReasonCode = app.adjTypeCode;
if (app.adjSource instanceof ProcessRecord) {
currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
+ currApp.importanceReasonImportance = oomAdjToImportance(
+ app.adjSourceOom, null);
} else if (app.adjSource instanceof ActivityRecord) {
ActivityRecord r = (ActivityRecord)app.adjSource;
if (r.app != null) currApp.importanceReasonPid = r.app.pid;
@@ -7891,7 +7931,7 @@
if (mLruProcesses.size() > 0) {
if (needSep) pw.println(" ");
needSep = true;
- pw.println(" Process LRU list (most recent first):");
+ pw.println(" Process LRU list (sorted by oom_adj):");
dumpProcessOomList(pw, this, mLruProcesses, " ",
"Proc", "PERS", false);
needSep = true;
@@ -8069,29 +8109,6 @@
boolean needSep = false;
if (mLruProcesses.size() > 0) {
- ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
-
- Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
- @Override
- public int compare(ProcessRecord object1, ProcessRecord object2) {
- if (object1.setAdj != object2.setAdj) {
- return object1.setAdj > object2.setAdj ? -1 : 1;
- }
- if (object1.setSchedGroup != object2.setSchedGroup) {
- return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
- }
- if (object1.keeping != object2.keeping) {
- return object1.keeping ? -1 : 1;
- }
- if (object1.pid != object2.pid) {
- return object1.pid > object2.pid ? -1 : 1;
- }
- return 0;
- }
- };
-
- Collections.sort(procs, comparator);
-
if (needSep) pw.println(" ");
needSep = true;
pw.println(" OOM levels:");
@@ -8110,7 +8127,7 @@
if (needSep) pw.println(" ");
needSep = true;
pw.println(" Process OOM control:");
- dumpProcessOomList(pw, this, procs, " ",
+ dumpProcessOomList(pw, this, mLruProcesses, " ",
"Proc", "PERS", true);
needSep = true;
}
@@ -8859,10 +8876,33 @@
}
private static final void dumpProcessOomList(PrintWriter pw,
- ActivityManagerService service, List<ProcessRecord> list,
+ ActivityManagerService service, List<ProcessRecord> origList,
String prefix, String normalLabel, String persistentLabel,
boolean inclDetails) {
+ ArrayList<Pair<ProcessRecord, Integer>> list
+ = new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
+ for (int i=0; i<origList.size(); i++) {
+ list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
+ }
+
+ Comparator<Pair<ProcessRecord, Integer>> comparator
+ = new Comparator<Pair<ProcessRecord, Integer>>() {
+ @Override
+ public int compare(Pair<ProcessRecord, Integer> object1,
+ Pair<ProcessRecord, Integer> object2) {
+ if (object1.first.setAdj != object2.first.setAdj) {
+ return object1.first.setAdj > object2.first.setAdj ? -1 : 1;
+ }
+ if (object1.second.intValue() != object2.second.intValue()) {
+ return object1.second.intValue() > object2.second.intValue() ? -1 : 1;
+ }
+ return 0;
+ }
+ };
+
+ Collections.sort(list, comparator);
+
final long curRealtime = SystemClock.elapsedRealtime();
final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
final long curUptime = SystemClock.uptimeMillis();
@@ -8870,7 +8910,7 @@
final int N = list.size()-1;
for (int i=N; i>=0; i--) {
- ProcessRecord r = list.get(i);
+ ProcessRecord r = list.get(i).first;
String oomAdj;
if (r.setAdj >= ProcessList.EMPTY_APP_ADJ) {
oomAdj = buildOomTag("empty", null, r.setAdj, ProcessList.EMPTY_APP_ADJ);
@@ -8919,7 +8959,7 @@
}
pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)",
prefix, (r.persistent ? persistentLabel : normalLabel),
- N-i, oomAdj, schedGroup, foreground, r.trimMemoryLevel,
+ N-list.get(i).second, oomAdj, schedGroup, foreground, r.trimMemoryLevel,
r.toShortString(), r.adjType));
if (r.adjSource != null || r.adjTarget != null) {
pw.print(prefix);
@@ -13118,6 +13158,7 @@
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_SERVICE_IN_USE;
app.adjSource = cr.binding.client;
+ app.adjSourceOom = clientAdj;
app.adjTarget = s.name;
}
if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
@@ -13140,6 +13181,7 @@
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_SERVICE_IN_USE;
app.adjSource = a;
+ app.adjSourceOom = adj;
app.adjTarget = s.name;
}
}
@@ -13201,6 +13243,7 @@
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_PROVIDER_IN_USE;
app.adjSource = client;
+ app.adjSourceOom = clientAdj;
app.adjTarget = cpr.name;
}
if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
@@ -13511,16 +13554,21 @@
computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
if (app.curRawAdj != app.setRawAdj) {
- if (app.curRawAdj > ProcessList.FOREGROUND_APP_ADJ
- && app.setRawAdj <= ProcessList.FOREGROUND_APP_ADJ) {
- // If this app is transitioning from foreground to
- // non-foreground, have it do a gc.
- scheduleAppGcLocked(app);
- } else if (app.curRawAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
- && app.setRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) {
- // Likewise do a gc when an app is moving in to the
- // background (such as a service stopping).
- scheduleAppGcLocked(app);
+ if (false) {
+ // Removing for now. Forcing GCs is not so useful anymore
+ // with Dalvik, and the new memory level hint facility is
+ // better for what we need to do these days.
+ if (app.curRawAdj > ProcessList.FOREGROUND_APP_ADJ
+ && app.setRawAdj <= ProcessList.FOREGROUND_APP_ADJ) {
+ // If this app is transitioning from foreground to
+ // non-foreground, have it do a gc.
+ scheduleAppGcLocked(app);
+ } else if (app.curRawAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
+ && app.setRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) {
+ // Likewise do a gc when an app is moving in to the
+ // background (such as a service stopping).
+ scheduleAppGcLocked(app);
+ }
}
if (wasKeeping && !app.keeping) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 4ad0f45..a0aedf9 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1151,6 +1151,7 @@
try {
mService.mWindowManager.setAppVisibility(r, true);
r.sleeping = false;
+ r.app.pendingUiClean = true;
r.app.thread.scheduleWindowVisibility(r, true);
r.stopFreezingScreenLocked(false);
} catch (Exception e) {
@@ -1497,6 +1498,7 @@
next.sleeping = false;
showAskCompatModeDialogLocked(next);
+ next.app.pendingUiClean = true;
next.app.thread.scheduleResumeActivity(next,
mService.isNextTransitionForward());
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 24d92cf..9392bb4 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -99,6 +99,7 @@
String adjType; // Debugging: primary thing impacting oom_adj.
int adjTypeCode; // Debugging: adj code to report to app.
Object adjSource; // Debugging: option dependent object.
+ int adjSourceOom; // Debugging: oom_adj of adjSource's process.
Object adjTarget; // Debugging: target component impacting oom_adj.
// contains HistoryRecord objects
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 8af90ff..9067fae 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -100,6 +100,7 @@
import android.telephony.TelephonyManager;
import android.text.format.Formatter;
import android.text.format.Time;
+import android.util.Log;
import android.util.NtpTrustedTime;
import android.util.Slog;
import android.util.SparseArray;
@@ -298,18 +299,9 @@
try {
mActivityManager.registerProcessObserver(mProcessObserver);
- } catch (RemoteException e) {
- // ouch, no foregroundActivities updates means some processes may
- // never get network access.
- Slog.e(TAG, "unable to register IProcessObserver", e);
- }
-
- try {
mNetworkManager.registerObserver(mAlertObserver);
} catch (RemoteException e) {
- // ouch, no alert updates means we fall back to
- // ACTION_NETWORK_STATS_UPDATED broadcasts.
- Slog.e(TAG, "unable to register INetworkManagementEventObserver", e);
+ // ignored; both services live in system_server
}
// TODO: traverse existing processes to know foreground state, or have
@@ -462,7 +454,7 @@
// caused alert to trigger.
mNetworkStats.forceUpdate();
} catch (RemoteException e) {
- Slog.w(TAG, "problem updating network stats");
+ // ignored; service lives in system_server
}
updateNetworkEnabledLocked();
@@ -495,9 +487,7 @@
final long start = computeLastCycleBoundary(currentTime, policy);
final long end = currentTime;
-
final long totalBytes = getTotalBytes(policy.template, start, end);
- if (totalBytes == UNKNOWN_BYTES) continue;
if (policy.limitBytes != LIMIT_DISABLED && totalBytes >= policy.limitBytes) {
if (policy.lastSnooze >= start) {
@@ -671,7 +661,7 @@
packageName, tag, 0x0, builder.getNotification(), idReceived);
mActiveNotifs.add(tag);
} catch (RemoteException e) {
- Slog.w(TAG, "problem during enqueueNotification: " + e);
+ // ignored; service lives in system_server
}
}
@@ -705,7 +695,7 @@
0x0, builder.getNotification(), idReceived);
mActiveNotifs.add(tag);
} catch (RemoteException e) {
- Slog.w(TAG, "problem during enqueueNotification: " + e);
+ // ignored; service lives in system_server
}
}
@@ -716,7 +706,7 @@
mNotifManager.cancelNotificationWithTag(
packageName, tag, 0x0);
} catch (RemoteException e) {
- Slog.w(TAG, "problem during enqueueNotification: " + e);
+ // ignored; service lives in system_server
}
}
@@ -758,9 +748,7 @@
final long start = computeLastCycleBoundary(currentTime, policy);
final long end = currentTime;
-
final long totalBytes = getTotalBytes(policy.template, start, end);
- if (totalBytes == UNKNOWN_BYTES) continue;
// disable data connection when over limit and not snoozed
final boolean overLimit = policy.limitBytes != LIMIT_DISABLED
@@ -810,7 +798,7 @@
try {
states = mConnManager.getAllNetworkState();
} catch (RemoteException e) {
- Slog.w(TAG, "problem reading network state");
+ // ignored; service lives in system_server
return;
}
@@ -857,9 +845,7 @@
final long start = computeLastCycleBoundary(currentTime, policy);
final long end = currentTime;
-
final long totalBytes = getTotalBytes(policy.template, start, end);
- if (totalBytes == UNKNOWN_BYTES) continue;
if (LOGD) {
Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
@@ -1006,9 +992,9 @@
// missing policy is okay, probably first boot
upgradeLegacyBackgroundData();
} catch (IOException e) {
- Slog.e(TAG, "problem reading network stats", e);
+ Log.wtf(TAG, "problem reading network policy", e);
} catch (XmlPullParserException e) {
- Slog.e(TAG, "problem reading network stats", e);
+ Log.wtf(TAG, "problem reading network policy", e);
} finally {
IoUtils.closeQuietly(fis);
}
@@ -1246,12 +1232,10 @@
final long currentTime = currentTimeMillis(false);
+ // find total bytes used under policy
final long start = computeLastCycleBoundary(currentTime, policy);
final long end = currentTime;
-
- // find total bytes used under policy
final long totalBytes = getTotalBytes(policy.template, start, end);
- if (totalBytes == UNKNOWN_BYTES) return null;
// report soft and hard limits under policy
final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes
@@ -1369,6 +1353,7 @@
try {
mScreenOn = mPowerManager.isScreenOn();
} catch (RemoteException e) {
+ // ignored; service lives in system_server
}
updateRulesForScreenLocked();
}
@@ -1448,7 +1433,7 @@
// adjust stats accounting based on foreground status
mNetworkStats.setUidForeground(uid, uidForeground);
} catch (RemoteException e) {
- Slog.w(TAG, "problem dispatching foreground change");
+ // ignored; service lives in system_server
}
}
@@ -1498,9 +1483,9 @@
try {
mNetworkManager.setInterfaceQuota(iface, quotaBytes);
} catch (IllegalStateException e) {
- Slog.e(TAG, "problem setting interface quota", e);
+ Log.wtf(TAG, "problem setting interface quota", e);
} catch (RemoteException e) {
- Slog.e(TAG, "problem setting interface quota", e);
+ // ignored; service lives in system_server
}
}
@@ -1508,29 +1493,9 @@
try {
mNetworkManager.removeInterfaceQuota(iface);
} catch (IllegalStateException e) {
- Slog.e(TAG, "problem removing interface quota", e);
+ Log.wtf(TAG, "problem removing interface quota", e);
} catch (RemoteException e) {
- Slog.e(TAG, "problem removing interface quota", e);
- }
- }
-
- private void setInterfaceAlert(String iface, long alertBytes) {
- try {
- mNetworkManager.setInterfaceAlert(iface, alertBytes);
- } catch (IllegalStateException e) {
- Slog.e(TAG, "problem setting interface alert", e);
- } catch (RemoteException e) {
- Slog.e(TAG, "problem setting interface alert", e);
- }
- }
-
- private void removeInterfaceAlert(String iface) {
- try {
- mNetworkManager.removeInterfaceAlert(iface);
- } catch (IllegalStateException e) {
- Slog.e(TAG, "problem removing interface alert", e);
- } catch (RemoteException e) {
- Slog.e(TAG, "problem removing interface alert", e);
+ // ignored; service lives in system_server
}
}
@@ -1538,9 +1503,9 @@
try {
mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
} catch (IllegalStateException e) {
- Slog.e(TAG, "problem setting uid rules", e);
+ Log.wtf(TAG, "problem setting uid rules", e);
} catch (RemoteException e) {
- Slog.e(TAG, "problem setting uid rules", e);
+ // ignored; service lives in system_server
}
}
@@ -1556,7 +1521,7 @@
try {
mConnManager.setPolicyDataEnable(networkType, enabled);
} catch (RemoteException e) {
- Slog.e(TAG, "problem setting network enabled", e);
+ // ignored; service lives in system_server
}
mActiveNetworkEnabled.put(networkType, enabled);
@@ -1569,8 +1534,6 @@
return telephony.getSubscriberId();
}
- private static final long UNKNOWN_BYTES = -1;
-
private long getTotalBytes(NetworkTemplate template, long start, long end) {
try {
final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
@@ -1578,8 +1541,8 @@
final NetworkStats.Entry entry = stats.getValues(0, null);
return entry.rxBytes + entry.txBytes;
} catch (RemoteException e) {
- Slog.w(TAG, "problem reading summary for template " + template);
- return UNKNOWN_BYTES;
+ // ignored; service lives in system_server
+ return 0;
}
}
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 4d54fd4..af29d85 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -79,6 +79,7 @@
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.EventLog;
+import android.util.Log;
import android.util.NtpTrustedTime;
import android.util.Slog;
import android.util.SparseIntArray;
@@ -128,7 +129,16 @@
private static final int VERSION_UID_WITH_SET = 4;
private static final int MSG_PERFORM_POLL = 0x1;
- private static final int MSG_PERFORM_POLL_DETAILED = 0x2;
+
+ /** Flags to control detail level of poll event. */
+ private static final int FLAG_POLL_NETWORK = 0x1;
+ private static final int FLAG_POLL_UID = 0x2;
+ private static final int FLAG_PERSIST_NETWORK = 0x10;
+ private static final int FLAG_PERSIST_UID = 0x20;
+ private static final int FLAG_FORCE_PERSIST = 0x100;
+
+ private static final int FLAG_POLL_ALL = FLAG_POLL_NETWORK | FLAG_POLL_UID;
+ private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
private final Context mContext;
private final INetworkManagementService mNetworkManager;
@@ -261,9 +271,7 @@
try {
mNetworkManager.registerObserver(mAlertObserver);
} catch (RemoteException e) {
- // ouch, no push updates means we fall back to
- // ACTION_NETWORK_STATS_POLL intervals.
- Slog.e(TAG, "unable to register INetworkManagementEventObserver", e);
+ // ignored; service lives in system_server
}
registerPollAlarmLocked();
@@ -305,7 +313,7 @@
mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
mSettings.getPollInterval(), mPollIntent);
} catch (RemoteException e) {
- Slog.w(TAG, "problem registering for poll alarm: " + e);
+ // ignored; service lives in system_server
}
}
@@ -321,7 +329,7 @@
} catch (IllegalStateException e) {
Slog.w(TAG, "problem registering for global alert: " + e);
} catch (RemoteException e) {
- Slog.w(TAG, "problem registering for global alert: " + e);
+ // ignored; service lives in system_server
}
}
@@ -509,7 +517,7 @@
@Override
public void forceUpdate() {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
- performPoll(true, false);
+ performPoll(FLAG_POLL_ALL | FLAG_PERSIST_ALL);
}
/**
@@ -538,7 +546,7 @@
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified UPDATE_DEVICE_STATS
// permission above.
- performPoll(true, false);
+ performPoll(FLAG_POLL_ALL | FLAG_PERSIST_ALL);
// verify that we're watching global alert
registerGlobalAlert();
@@ -585,7 +593,8 @@
if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
// kick off background poll to collect network stats; UID stats
// are handled during normal polling interval.
- mHandler.obtainMessage(MSG_PERFORM_POLL).sendToTarget();
+ final int flags = FLAG_POLL_NETWORK | FLAG_PERSIST_NETWORK;
+ mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget();
// re-arm global alert for next update
registerGlobalAlert();
@@ -605,13 +614,17 @@
// take one last stats snapshot before updating iface mapping. this
// isn't perfect, since the kernel may already be counting traffic from
// the updated network.
- performPollLocked(false, false);
+
+ // poll both network and UID stats, but only persist network stats,
+ // since this codepath should stay fast. UID stats will be persisted
+ // during next alarm poll event.
+ performPollLocked(FLAG_POLL_ALL | FLAG_PERSIST_NETWORK);
final NetworkState[] states;
try {
states = mConnManager.getAllNetworkState();
} catch (RemoteException e) {
- Slog.w(TAG, "problem reading network state");
+ // ignored; service lives in system_server
return;
}
@@ -646,15 +659,15 @@
} catch (IllegalStateException e) {
Slog.w(TAG, "problem reading network stats: " + e);
} catch (RemoteException e) {
- Slog.w(TAG, "problem reading network stats: " + e);
+ // ignored; service lives in system_server
}
}
- private void performPoll(boolean detailedPoll, boolean forcePersist) {
+ private void performPoll(int flags) {
synchronized (mStatsLock) {
mWakeLock.acquire();
try {
- performPollLocked(detailedPoll, forcePersist);
+ performPollLocked(flags);
} finally {
mWakeLock.release();
}
@@ -664,14 +677,17 @@
/**
* Periodic poll operation, reading current statistics and recording into
* {@link NetworkStatsHistory}.
- *
- * @param detailedPoll Indicate if detailed UID stats should be collected
- * during this poll operation.
*/
- private void performPollLocked(boolean detailedPoll, boolean forcePersist) {
- if (LOGV) Slog.v(TAG, "performPollLocked()");
+ private void performPollLocked(int flags) {
+ if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
final long startRealtime = SystemClock.elapsedRealtime();
+ final boolean pollNetwork = (flags & FLAG_POLL_NETWORK) != 0;
+ final boolean pollUid = (flags & FLAG_POLL_UID) != 0;
+ final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
+ final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
+ final boolean forcePersist = (flags & FLAG_FORCE_PERSIST) != 0;
+
// try refreshing time source when stale
if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
mTime.forceRefresh();
@@ -680,41 +696,40 @@
// TODO: consider marking "untrusted" times in historical stats
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
- final long persistThreshold = mSettings.getPersistThreshold();
+ final long threshold = mSettings.getPersistThreshold();
- final NetworkStats networkSnapshot;
- final NetworkStats uidSnapshot;
try {
- networkSnapshot = mNetworkManager.getNetworkStatsSummary();
- uidSnapshot = detailedPoll ? mNetworkManager.getNetworkStatsUidDetail(UID_ALL) : null;
- } catch (IllegalStateException e) {
- Slog.w(TAG, "problem reading network stats: " + e);
- return;
- } catch (RemoteException e) {
- Slog.w(TAG, "problem reading network stats: " + e);
- return;
- }
+ if (pollNetwork) {
+ final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary();
+ performNetworkPollLocked(networkSnapshot, currentTime);
- performNetworkPollLocked(networkSnapshot, currentTime);
-
- // persist when enough network data has occurred
- final NetworkStats persistNetworkDelta = computeStatsDelta(
- mLastPersistNetworkSnapshot, networkSnapshot, true);
- if (forcePersist || persistNetworkDelta.getTotalBytes() > persistThreshold) {
- writeNetworkStatsLocked();
- mLastPersistNetworkSnapshot = networkSnapshot;
- }
-
- if (detailedPoll) {
- performUidPollLocked(uidSnapshot, currentTime);
-
- // persist when enough network data has occurred
- final NetworkStats persistUidDelta = computeStatsDelta(
- mLastPersistUidSnapshot, uidSnapshot, true);
- if (forcePersist || persistUidDelta.getTotalBytes() > persistThreshold) {
- writeUidStatsLocked();
- mLastPersistUidSnapshot = networkSnapshot;
+ // persist when enough network data has occurred
+ final NetworkStats persistNetworkDelta = computeStatsDelta(
+ mLastPersistNetworkSnapshot, networkSnapshot, true);
+ final boolean pastThreshold = persistNetworkDelta.getTotalBytes() > threshold;
+ if (forcePersist || (persistNetwork && pastThreshold)) {
+ writeNetworkStatsLocked();
+ mLastPersistNetworkSnapshot = networkSnapshot;
+ }
}
+
+ if (pollUid) {
+ final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
+ performUidPollLocked(uidSnapshot, currentTime);
+
+ // persist when enough network data has occurred
+ final NetworkStats persistUidDelta = computeStatsDelta(
+ mLastPersistUidSnapshot, uidSnapshot, true);
+ final boolean pastThreshold = persistUidDelta.getTotalBytes() > threshold;
+ if (forcePersist || (persistUid && pastThreshold)) {
+ writeUidStatsLocked();
+ mLastPersistUidSnapshot = uidSnapshot;
+ }
+ }
+ } catch (IllegalStateException e) {
+ Log.wtf(TAG, "problem reading network stats", e);
+ } catch (RemoteException e) {
+ // ignored; service lives in system_server
}
if (LOGV) {
@@ -722,8 +737,8 @@
Slog.v(TAG, "performPollLocked() took " + duration + "ms");
}
- // sample stats after detailed poll
- if (detailedPoll) {
+ // sample stats after each full poll
+ if (pollNetwork && pollUid) {
performSample();
}
@@ -785,6 +800,10 @@
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 UID delta from unknown iface: " + entry);
+ }
continue;
}
@@ -959,7 +978,7 @@
} catch (FileNotFoundException e) {
// missing stats is okay, probably first boot
} catch (IOException e) {
- Slog.e(TAG, "problem reading network stats", e);
+ Log.wtf(TAG, "problem reading network stats", e);
} finally {
IoUtils.closeQuietly(in);
}
@@ -1032,7 +1051,7 @@
} catch (FileNotFoundException e) {
// missing stats is okay, probably first boot
} catch (IOException e) {
- Slog.e(TAG, "problem reading uid stats", e);
+ Log.wtf(TAG, "problem reading uid stats", e);
} finally {
IoUtils.closeQuietly(in);
}
@@ -1061,7 +1080,7 @@
out.flush();
mNetworkFile.finishWrite(fos);
} catch (IOException e) {
- Slog.w(TAG, "problem writing stats: ", e);
+ Log.wtf(TAG, "problem writing stats", e);
if (fos != null) {
mNetworkFile.failWrite(fos);
}
@@ -1115,7 +1134,7 @@
out.flush();
mUidFile.finishWrite(fos);
} catch (IOException e) {
- Slog.w(TAG, "problem writing stats: ", e);
+ Log.wtf(TAG, "problem writing stats", e);
if (fos != null) {
mUidFile.failWrite(fos);
}
@@ -1142,7 +1161,7 @@
}
if (argSet.contains("poll")) {
- performPollLocked(true, true);
+ performPollLocked(FLAG_POLL_ALL | FLAG_PERSIST_ALL | FLAG_FORCE_PERSIST);
pw.println("Forced poll");
return;
}
@@ -1273,11 +1292,8 @@
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_PERFORM_POLL: {
- performPoll(false, false);
- return true;
- }
- case MSG_PERFORM_POLL_DETAILED: {
- performPoll(true, false);
+ final int flags = msg.arg1;
+ performPoll(flags);
return true;
}
default: {
@@ -1349,7 +1365,7 @@
return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
}
public long getPersistThreshold() {
- return getSecureLong(NETSTATS_PERSIST_THRESHOLD, 512 * KB_IN_BYTES);
+ return getSecureLong(NETSTATS_PERSIST_THRESHOLD, 2 * MB_IN_BYTES);
}
public long getNetworkBucketDuration() {
return getSecureLong(NETSTATS_NETWORK_BUCKET_DURATION, HOUR_IN_MILLIS);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 755a268..211c4da 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -5824,27 +5824,6 @@
config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
- // We need to determine the smallest width that will occur under normal
- // operation. To this, start with the base screen size and compute the
- // width under the different possible rotations. We need to un-rotate
- // the current screen dimensions before doing this.
- int unrotDw, unrotDh;
- if (rotated) {
- unrotDw = dh;
- unrotDh = dw;
- } else {
- unrotDw = dw;
- unrotDh = dh;
- }
- config.smallestScreenWidthDp = reduceConfigWidthSize(unrotDw,
- Surface.ROTATION_0, dm.density, unrotDw);
- config.smallestScreenWidthDp = reduceConfigWidthSize(config.smallestScreenWidthDp,
- Surface.ROTATION_90, dm.density, unrotDh);
- config.smallestScreenWidthDp = reduceConfigWidthSize(config.smallestScreenWidthDp,
- Surface.ROTATION_180, dm.density, unrotDw);
- config.smallestScreenWidthDp = reduceConfigWidthSize(config.smallestScreenWidthDp,
- Surface.ROTATION_270, dm.density, unrotDh);
-
// Compute the screen layout size class.
int screenLayout;
int longSize = dw;
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 54f3bb0..e7f1d9a 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -178,6 +178,7 @@
expectDefaultSettings();
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -230,6 +231,7 @@
expectDefaultSettings();
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -320,6 +322,7 @@
expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -370,6 +373,7 @@
expectDefaultSettings();
expectNetworkState(buildMobile3gState(IMSI_1));
expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -450,6 +454,7 @@
expectDefaultSettings();
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -507,6 +512,7 @@
expectDefaultSettings();
expectNetworkState(buildMobile3gState(IMSI_1));
expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -573,6 +579,7 @@
expectDefaultSettings();
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -635,6 +642,7 @@
expectDefaultSettings();
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index aa7568b..f769157 100644
--- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -113,10 +113,15 @@
TelephonyManager telephony = TelephonyManager.getDefault();
LinkProperties linkProperties = null;
LinkCapabilities linkCapabilities = null;
+ boolean roaming = false;
+
if (state == Phone.DataState.CONNECTED) {
linkProperties = sender.getLinkProperties(apnType);
linkCapabilities = sender.getLinkCapabilities(apnType);
}
+ ServiceState ss = sender.getServiceState();
+ if (ss != null) roaming = ss.getRoaming();
+
try {
mRegistry.notifyDataConnection(
convertDataState(state),
@@ -126,7 +131,8 @@
linkProperties,
linkCapabilities,
((telephony!=null) ? telephony.getNetworkType() :
- TelephonyManager.NETWORK_TYPE_UNKNOWN));
+ TelephonyManager.NETWORK_TYPE_UNKNOWN),
+ roaming);
} catch (RemoteException ex) {
// system process is dead
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 3c83e50..1f19282 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -35,7 +35,7 @@
void notifyDataActivity(int state);
void notifyDataConnection(int state, boolean isDataConnectivityPossible,
String reason, String apn, String apnType, in LinkProperties linkProperties,
- in LinkCapabilities linkCapabilities, int networkType);
+ in LinkCapabilities linkCapabilities, int networkType, boolean roaming);
void notifyDataConnectionFailed(String reason, String apnType);
void notifyCellLocation(in Bundle cellLocation);
void notifyOtaspChanged(in int otaspMode);
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 6347f37..5e64148 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -106,6 +106,7 @@
static final String DATA_IFACE_NAME_KEY = "iface";
static final String NETWORK_UNAVAILABLE_KEY = "networkUnvailable";
+ static final String DATA_NETWORK_ROAMING_KEY = "networkRoaming";
static final String PHONE_IN_ECM_STATE = "phoneinECMState";
/**
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 1a077d00e..a728d0a 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -582,7 +582,12 @@
*/
@Override
protected void onRoamingOff() {
- trySetupData(Phone.REASON_ROAMING_OFF);
+ if (getDataOnRoamingEnabled() == false) {
+ notifyDataAvailability(Phone.REASON_ROAMING_OFF);
+ trySetupData(Phone.REASON_ROAMING_OFF);
+ } else {
+ notifyDataConnection(Phone.REASON_ROAMING_OFF);
+ }
}
/**
@@ -592,9 +597,11 @@
protected void onRoamingOn() {
if (getDataOnRoamingEnabled()) {
trySetupData(Phone.REASON_ROAMING_ON);
+ notifyDataConnection(Phone.REASON_ROAMING_ON);
} else {
if (DBG) log("Tear down data connection on roaming.");
cleanUpAllConnections(null);
+ notifyDataAvailability(Phone.REASON_ROAMING_ON);
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 00fb0e0..4e43fcd 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -1681,23 +1681,25 @@
@Override
protected void onRoamingOff() {
if (DBG) log("onRoamingOff");
- // Notify data availability so APN can be enabled.
- notifyDataAvailability(Phone.REASON_ROAMING_OFF);
- setupDataOnReadyApns(Phone.REASON_ROAMING_OFF);
+ if (getDataOnRoamingEnabled() == false) {
+ notifyDataAvailability(Phone.REASON_ROAMING_OFF);
+ setupDataOnReadyApns(Phone.REASON_ROAMING_OFF);
+ } else {
+ notifyDataConnection(Phone.REASON_ROAMING_OFF);
+ }
}
@Override
protected void onRoamingOn() {
- // Notify data availability so APN can be enabled.
- notifyDataAvailability(Phone.REASON_ROAMING_ON);
-
if (getDataOnRoamingEnabled()) {
if (DBG) log("onRoamingOn: setup data on roaming");
setupDataOnReadyApns(Phone.REASON_ROAMING_ON);
+ notifyDataConnection(Phone.REASON_ROAMING_ON);
} else {
if (DBG) log("onRoamingOn: Tear down data connection on roaming.");
cleanUpAllConnections(true, Phone.REASON_ROAMING_ON);
+ notifyDataAvailability(Phone.REASON_ROAMING_ON);
}
}
diff --git a/tests/DataIdleTest/Android.mk b/tests/DataIdleTest/Android.mk
new file mode 100644
index 0000000..acb46c5
--- /dev/null
+++ b/tests/DataIdleTest/Android.mk
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_PACKAGE_NAME := DataIdleTest
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# We need to sign it to get access to the network usage history.
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/tests/DataIdleTest/AndroidManifest.xml b/tests/DataIdleTest/AndroidManifest.xml
new file mode 100644
index 0000000..2792eec
--- /dev/null
+++ b/tests/DataIdleTest/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.dataidle"
+ android:sharedUserId="android.uid.system">
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
+ <application >
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.tests.dataidle"
+ android:label="Idle Bandwidth Tests" />
+
+</manifest>
diff --git a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
new file mode 100644
index 0000000..637f0d2
--- /dev/null
+++ b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.dataidle;
+
+import android.content.Context;
+import android.net.INetworkStatsService;
+import android.net.NetworkStats.Entry;
+import android.net.NetworkTemplate;
+import android.net.NetworkStats;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.telephony.TelephonyManager;
+import android.test.InstrumentationTestCase;
+import android.test.InstrumentationTestRunner;
+import android.util.Log;
+
+/**
+ * A test that dumps data usage to instrumentation out, used for measuring data usage for idle
+ * devices.
+ */
+public class DataIdleTest extends InstrumentationTestCase {
+
+ private TelephonyManager mTelephonyManager;
+ private INetworkStatsService mStatsService;
+
+ private static final String LOG_TAG = "DataIdleTest";
+ private final static int INSTRUMENTATION_IN_PROGRESS = 2;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ Context c = getInstrumentation().getTargetContext();
+ mStatsService = INetworkStatsService.Stub.asInterface(
+ ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+ mTelephonyManager = (TelephonyManager) c.getSystemService(Context.TELEPHONY_SERVICE);
+ }
+
+ /**
+ * Test that dumps all the data usage metrics for wifi to instrumentation out.
+ */
+ public void testWifiIdle() {
+ NetworkTemplate template = NetworkTemplate.buildTemplateWifi();
+ fetchStats(template);
+ }
+
+ /**
+ * Test that dumps all the data usage metrics for all mobile to instrumentation out.
+ */
+ public void testMobile() {
+ String subscriberId = mTelephonyManager.getSubscriberId();
+ NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
+ fetchStats(template);
+ }
+
+ /**
+ * Helper method that fetches all the network stats available and reports it
+ * to instrumentation out.
+ * @param template {link {@link NetworkTemplate} to match.
+ */
+ private void fetchStats(NetworkTemplate template) {
+ try {
+ NetworkStats stats = mStatsService.getSummaryForAllUid(template, Long.MIN_VALUE,
+ Long.MAX_VALUE, false);
+ reportStats(stats);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Failed to fetch network stats for wifi.");
+ }
+ }
+
+ /**
+ * Print network data usage stats to instrumentation out
+ * @param stats {@link NetworkorStats} to print
+ */
+ void reportStats(NetworkStats stats) {
+ for (int i = 0; i < stats.size(); ++i) {
+ Entry statsEntry = stats.getValues(i, null);
+ Bundle result = new Bundle();
+ result.putInt("uid", statsEntry.uid);
+ result.putInt("tag", statsEntry.tag);
+ result.putInt("set", statsEntry.set);
+ result.putString("iface", statsEntry.iface);
+ result.putLong("rxBytes", statsEntry.rxBytes);
+ result.putLong("txBytes", statsEntry.txBytes);
+ getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, result);
+ }
+ }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/Android.mk b/tests/RenderScriptTests/ImageProcessing/Android.mk
index 507cc92..d7486e8 100644
--- a/tests/RenderScriptTests/ImageProcessing/Android.mk
+++ b/tests/RenderScriptTests/ImageProcessing/Android.mk
@@ -17,7 +17,9 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
$(call all-renderscript-files-under, src)
diff --git a/tests/RenderScriptTests/ImageProcessing/AndroidManifest.xml b/tests/RenderScriptTests/ImageProcessing/AndroidManifest.xml
index 174cc65..2232b98 100644
--- a/tests/RenderScriptTests/ImageProcessing/AndroidManifest.xml
+++ b/tests/RenderScriptTests/ImageProcessing/AndroidManifest.xml
@@ -2,10 +2,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.rs.image">
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-sdk android:minSdkVersion="11" />
<application android:label="Image Processing"
android:hardwareAccelerated="true">
+ <uses-library android:name="android.test.runner" />
<activity android:name="ImageProcessingActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -13,4 +14,9 @@
</intent-filter>
</activity>
</application>
+
+ <instrumentation android:name=".ImageProcessingTestRunner"
+ android:targetPackage="com.android.rs.image"
+ android:label="Test runner for Image Processing Benchmark Test"
+ />
</manifest>
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 9aa70b0..3615f60 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -33,11 +33,13 @@
import android.widget.SeekBar;
import android.widget.TextView;
import android.view.View;
+import android.util.Log;
import java.lang.Math;
public class ImageProcessingActivity extends Activity
implements SurfaceHolder.Callback,
SeekBar.OnSeekBarChangeListener {
+ private final String TAG = "Img";
private Bitmap mBitmapIn;
private Bitmap mBitmapOut;
private ScriptC_threshold mScript;
@@ -268,7 +270,15 @@
// button hook
public void benchmark(View v) {
- android.util.Log.v("Img", "Benchmarking");
+ long t = getBenchmark();
+ //long javaTime = javaFilter();
+ //mBenchmarkResult.setText("RS: " + t + " ms Java: " + javaTime + " ms");
+ mBenchmarkResult.setText("Result: " + t + " ms");
+ }
+
+ // For benchmark test
+ public long getBenchmark() {
+ Log.v(TAG, "Benchmarking");
int oldRadius = mRadius;
mRadius = MAX_RADIUS;
mScript.set_radius(mRadius);
@@ -279,16 +289,12 @@
mOutPixelsAllocation.copyTo(mBitmapOut);
t = java.lang.System.currentTimeMillis() - t;
- android.util.Log.v("Img", "Renderscript frame time core ms " + t);
-
- //long javaTime = javaFilter();
- //mBenchmarkResult.setText("RS: " + t + " ms Java: " + javaTime + " ms");
- mBenchmarkResult.setText("Result: " + t + " ms");
-
+ Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
mRadius = oldRadius;
mScript.set_radius(mRadius);
mScript.invoke_filter();
mOutPixelsAllocation.copyTo(mBitmapOut);
+ return t;
}
}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingTest.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingTest.java
new file mode 100644
index 0000000..d2298da
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image;
+
+import android.os.Bundle;
+import android.os.Environment;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+/**
+ * ImageProcessing benchmark test.
+ * To run the test, please use command
+ *
+ * adb shell am instrument -w com.android.rs.image/.ImageProcessingTestRunner
+ *
+ */
+public class ImageProcessingTest extends ActivityInstrumentationTestCase2<ImageProcessingActivity> {
+ private final String TAG = "ImageProcessingTest";
+ private final String RESULT_FILE = "image_processing_result.txt";
+ private ImageProcessingActivity mAct;
+
+ public ImageProcessingTest() {
+ super(ImageProcessingActivity.class);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mAct = getActivity();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * ImageProcessing benchmark test
+ */
+ @LargeTest
+ public void testImageProcessingBench() {
+ long t = mAct.getBenchmark();
+ Log.v(TAG, "t = " + t);
+
+ // write result into a file
+ File externalStorage = Environment.getExternalStorageDirectory();
+ if (!externalStorage.canWrite()) {
+ Log.v(TAG, "sdcard is not writable");
+ return;
+ }
+ File resultFile = new File(externalStorage, RESULT_FILE);
+ resultFile.setWritable(true, false);
+ try {
+ BufferedWriter results = new BufferedWriter(new FileWriter(resultFile));
+ results.write("Renderscript frame time core: " + t + " ms");
+ results.close();
+ Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
+ } catch (IOException e) {
+ Log.v(TAG, "Unable to write result file " + e.getMessage());
+ }
+ }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingTestRunner.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingTestRunner.java
new file mode 100644
index 0000000..4e27b7f
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingTestRunner.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image;
+
+import com.android.rs.image.ImageProcessingTest;
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+import junit.framework.TestSuite;
+
+/**
+ * Run the ImageProcessing benchmark test
+ * adb shell am instrument -w com.android.rs.image/.ImageProcessingTestRunner
+ *
+ */
+public class ImageProcessingTestRunner extends InstrumentationTestRunner {
+ @Override
+ public TestSuite getAllTests() {
+ TestSuite suite = new InstrumentationTestSuite(this);
+ suite.addTestSuite(ImageProcessingTest.class);
+ return suite;
+ }
+}
diff --git a/voip/jni/rtp/AmrCodec.cpp b/voip/jni/rtp/AmrCodec.cpp
index 84c7166..e2d820e 100644
--- a/voip/jni/rtp/AmrCodec.cpp
+++ b/voip/jni/rtp/AmrCodec.cpp
@@ -52,7 +52,7 @@
int set(int sampleRate, const char *fmtp);
int encode(void *payload, int16_t *samples);
- int decode(int16_t *samples, void *payload, int length);
+ int decode(int16_t *samples, int count, void *payload, int length);
private:
void *mEncoder;
@@ -128,7 +128,7 @@
return length;
}
-int AmrCodec::decode(int16_t *samples, void *payload, int length)
+int AmrCodec::decode(int16_t *samples, int count, void *payload, int length)
{
unsigned char *bytes = (unsigned char *)payload;
Frame_Type_3GPP type;
@@ -213,7 +213,7 @@
}
int encode(void *payload, int16_t *samples);
- int decode(int16_t *samples, void *payload, int length);
+ int decode(int16_t *samples, int count, void *payload, int length);
private:
void *mEncoder;
@@ -239,20 +239,24 @@
return -1;
}
-int GsmEfrCodec::decode(int16_t *samples, void *payload, int length)
+int GsmEfrCodec::decode(int16_t *samples, int count, void *payload, int length)
{
unsigned char *bytes = (unsigned char *)payload;
- if (length == 31 && (bytes[0] >> 4) == 0x0C) {
+ int n = 0;
+ while (n + 160 <= count && length >= 31 && (bytes[0] >> 4) == 0x0C) {
for (int i = 0; i < 30; ++i) {
bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4);
}
bytes[30] <<= 4;
- if (AMRDecode(mDecoder, AMR_122, bytes, samples, MIME_IETF) == 31) {
- return 160;
+ if (AMRDecode(mDecoder, AMR_122, bytes, &samples[n], MIME_IETF) != 31) {
+ break;
}
+ n += 160;
+ length -= 31;
+ bytes += 31;
}
- return -1;
+ return n;
}
} // namespace
diff --git a/voip/jni/rtp/AudioCodec.h b/voip/jni/rtp/AudioCodec.h
index e389255..741730b 100644
--- a/voip/jni/rtp/AudioCodec.h
+++ b/voip/jni/rtp/AudioCodec.h
@@ -30,7 +30,7 @@
// Returns the length of payload in bytes.
virtual int encode(void *payload, int16_t *samples) = 0;
// Returns the number of decoded samples.
- virtual int decode(int16_t *samples, void *payload, int length) = 0;
+ virtual int decode(int16_t *samples, int count, void *payload, int length) = 0;
};
AudioCodec *newAudioCodec(const char *codecName);
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 5f07bb5..93c809e 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -395,7 +395,8 @@
mLatencyTimer = tick;
}
- if (mBufferTail - mBufferHead > BUFFER_SIZE - mInterval) {
+ int count = (BUFFER_SIZE - (mBufferTail - mBufferHead)) * mSampleRate;
+ if (count < mSampleCount) {
// Buffer overflow. Drop the packet.
LOGV("stream[%d] buffer overflow", mSocket);
recv(mSocket, &c, 1, MSG_DONTWAIT);
@@ -403,19 +404,18 @@
}
// Receive the packet and decode it.
- int16_t samples[mSampleCount];
- int length = 0;
+ int16_t samples[count];
if (!mCodec) {
// Special case for device stream.
- length = recv(mSocket, samples, sizeof(samples),
+ count = recv(mSocket, samples, sizeof(samples),
MSG_TRUNC | MSG_DONTWAIT) >> 1;
} else {
__attribute__((aligned(4))) uint8_t buffer[2048];
sockaddr_storage remote;
- socklen_t len = sizeof(remote);
+ socklen_t addrlen = sizeof(remote);
- length = recvfrom(mSocket, buffer, sizeof(buffer),
- MSG_TRUNC | MSG_DONTWAIT, (sockaddr *)&remote, &len);
+ int length = recvfrom(mSocket, buffer, sizeof(buffer),
+ MSG_TRUNC | MSG_DONTWAIT, (sockaddr *)&remote, &addrlen);
// Do we need to check SSRC, sequence, and timestamp? They are not
// reliable but at least they can be used to identify duplicates?
@@ -433,14 +433,15 @@
}
length -= offset;
if (length >= 0) {
- length = mCodec->decode(samples, &buffer[offset], length);
+ length = mCodec->decode(samples, count, &buffer[offset], length);
}
if (length > 0 && mFixRemote) {
mRemote = remote;
mFixRemote = false;
}
+ count = length;
}
- if (length <= 0) {
+ if (count <= 0) {
LOGV("stream[%d] decoder error", mSocket);
return;
}
@@ -462,7 +463,7 @@
// Append to the jitter buffer.
int tail = mBufferTail * mSampleRate;
- for (int i = 0; i < mSampleCount; ++i) {
+ for (int i = 0; i < count; ++i) {
mBuffer[tail & mBufferMask] = samples[i];
++tail;
}
diff --git a/voip/jni/rtp/G711Codec.cpp b/voip/jni/rtp/G711Codec.cpp
index a467acf..ef54863 100644
--- a/voip/jni/rtp/G711Codec.cpp
+++ b/voip/jni/rtp/G711Codec.cpp
@@ -39,7 +39,7 @@
return mSampleCount;
}
int encode(void *payload, int16_t *samples);
- int decode(int16_t *samples, void *payload, int length);
+ int decode(int16_t *samples, int count, void *payload, int length);
private:
int mSampleCount;
};
@@ -64,9 +64,12 @@
return mSampleCount;
}
-int UlawCodec::decode(int16_t *samples, void *payload, int length)
+int UlawCodec::decode(int16_t *samples, int count, void *payload, int length)
{
int8_t *ulaws = (int8_t *)payload;
+ if (length > count) {
+ length = count;
+ }
for (int i = 0; i < length; ++i) {
int ulaw = ~ulaws[i];
int exponent = (ulaw >> 4) & 0x07;
@@ -87,7 +90,7 @@
return mSampleCount;
}
int encode(void *payload, int16_t *samples);
- int decode(int16_t *samples, void *payload, int length);
+ int decode(int16_t *samples, int count, void *payload, int length);
private:
int mSampleCount;
};
@@ -111,9 +114,12 @@
return mSampleCount;
}
-int AlawCodec::decode(int16_t *samples, void *payload, int length)
+int AlawCodec::decode(int16_t *samples, int count, void *payload, int length)
{
int8_t *alaws = (int8_t *)payload;
+ if (length > count) {
+ length = count;
+ }
for (int i = 0; i < length; ++i) {
int alaw = alaws[i] ^ 0x55;
int exponent = (alaw >> 4) & 0x07;
diff --git a/voip/jni/rtp/GsmCodec.cpp b/voip/jni/rtp/GsmCodec.cpp
index 8d2286e..61dfdc9 100644
--- a/voip/jni/rtp/GsmCodec.cpp
+++ b/voip/jni/rtp/GsmCodec.cpp
@@ -44,7 +44,7 @@
}
int encode(void *payload, int16_t *samples);
- int decode(int16_t *samples, void *payload, int length);
+ int decode(int16_t *samples, int count, void *payload, int length);
private:
gsm mEncode;
@@ -57,13 +57,17 @@
return 33;
}
-int GsmCodec::decode(int16_t *samples, void *payload, int length)
+int GsmCodec::decode(int16_t *samples, int count, void *payload, int length)
{
- if (length == 33 &&
- gsm_decode(mDecode, (unsigned char *)payload, samples) == 0) {
- return 160;
+ unsigned char *bytes = (unsigned char *)payload;
+ int n = 0;
+ while (n + 160 <= count && length >= 33 &&
+ gsm_decode(mDecode, bytes, &samples[n]) == 0) {
+ n += 160;
+ length -= 33;
+ bytes += 33;
}
- return -1;
+ return n;
}
} // namespace
diff --git a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
index a0c7dd1..381a450 100644
--- a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
+++ b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
@@ -26,6 +26,5 @@
interface IWifiP2pManager
{
Messenger getMessenger();
- boolean isP2pSupported();
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 10a316e..5715186 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -400,15 +400,6 @@
}
}
- /** @hide */
- public boolean isP2pSupported() {
- try {
- return mService.isP2pSupported();
- } catch (RemoteException e) {
- return false;
- }
- }
-
/**
* Sends in a request to the system to enable p2p. This will pop up a dialog
* to the user and upon authorization will enable p2p.
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 361cac5..e2b2249 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -155,8 +155,9 @@
mInterface = SystemProperties.get("wifi.interface", "wlan0");
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
- mP2pSupported = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_wifi_p2p_support);
+ mP2pSupported = mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_WIFI_DIRECT);
+
mDeviceType = mContext.getResources().getString(
com.android.internal.R.string.config_wifi_p2p_device_type);
mDeviceName = getDefaultDeviceName();
@@ -218,14 +219,6 @@
return new Messenger(mP2pStateMachine.getHandler());
}
- /**
- * Return if p2p is supported
- */
- public boolean isP2pSupported() {
- enforceAccessPermission();
- return mP2pSupported;
- }
-
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -1218,6 +1211,11 @@
mReplyChannel.replyToMessage(msg, what);
}
+ private void replyToMessage(Message msg, int what, int arg1) {
+ if (msg.replyTo == null) return;
+ mReplyChannel.replyToMessage(msg, what, arg1);
+ }
+
private void replyToMessage(Message msg, int what, Object obj) {
if (msg.replyTo == null) return;
mReplyChannel.replyToMessage(msg, what, obj);