summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/ActivityThread.java51
-rw-r--r--core/java/android/app/ApplicationThreadNative.java18
-rw-r--r--core/java/android/app/IApplicationThread.java2
-rw-r--r--core/java/android/app/Notification.java77
-rw-r--r--core/java/android/bluetooth/BluetoothInputDevice.java14
-rw-r--r--core/java/android/content/Intent.java9
-rw-r--r--core/java/android/content/res/ColorStateList.java18
-rw-r--r--core/java/android/content/res/Resources.java37
-rw-r--r--core/java/android/net/CaptivePortalTracker.java7
-rw-r--r--core/java/android/os/BatteryStats.java325
-rw-r--r--core/java/android/transition/Transition.java28
-rw-r--r--core/java/android/transition/TransitionManager.java6
-rw-r--r--core/java/android/transition/TransitionSet.java12
-rw-r--r--core/java/android/view/KeyEvent.java14
-rw-r--r--core/java/android/view/SurfaceView.java5
-rw-r--r--core/java/android/view/TextureView.java5
-rw-r--r--core/java/android/view/View.java36
-rw-r--r--core/java/android/view/ViewGroup.java4
-rw-r--r--core/java/android/view/inputmethod/EditorInfo.java139
-rw-r--r--core/java/android/view/inputmethod/InputMethodInfo.java27
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java8
-rw-r--r--core/java/android/view/inputmethod/InputMethodSubtypeArray.java278
-rw-r--r--core/java/android/webkit/WebView.java5
-rw-r--r--core/java/android/widget/AbsListView.java10
-rw-r--r--core/java/android/widget/TextView.java7
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java78
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl2
-rw-r--r--core/java/com/android/internal/view/RotationPolicy.java5
28 files changed, 962 insertions, 265 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3258585..138eea2 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -71,6 +71,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.transition.Scene;
import android.transition.TransitionManager;
+import android.provider.Settings;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
@@ -110,6 +111,7 @@ import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.net.InetAddress;
import java.security.Security;
+import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -750,8 +752,42 @@ public final class ActivityThread {
setCoreSettings(coreSettings);
- // Tell the VMRuntime about the application.
- VMRuntime.registerAppInfo(appInfo.dataDir, appInfo.processName);
+ /*
+ * Two possible indications that this package could be
+ * sharing its runtime with other packages:
+ *
+ * 1.) the sharedUserId attribute is set in the manifest,
+ * indicating a request to share a VM with other
+ * packages with the same sharedUserId.
+ *
+ * 2.) the application element of the manifest has an
+ * attribute specifying a non-default process name,
+ * indicating the desire to run in another packages VM.
+ *
+ * If sharing is enabled we do not have a unique application
+ * in a process and therefore cannot rely on the package
+ * name inside the runtime.
+ */
+ IPackageManager pm = getPackageManager();
+ android.content.pm.PackageInfo pi = null;
+ try {
+ pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId());
+ } catch (RemoteException e) {
+ }
+ if (pi != null) {
+ boolean sharedUserIdSet = (pi.sharedUserId != null);
+ boolean processNameNotDefault =
+ (pi.applicationInfo != null &&
+ !appInfo.packageName.equals(pi.applicationInfo.processName));
+ boolean sharable = (sharedUserIdSet || processNameNotDefault);
+
+ // Tell the VMRuntime about the application, unless it is shared
+ // inside a process.
+ if (!sharable) {
+ VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir,
+ appInfo.processName);
+ }
+ }
AppBindData data = new AppBindData();
data.processName = processName;
@@ -1103,6 +1139,11 @@ public final class ActivityThread {
public void scheduleInstallProvider(ProviderInfo provider) {
sendMessage(H.INSTALL_PROVIDER, provider);
}
+
+ @Override
+ public final void updateTimePrefs(boolean is24Hour) {
+ DateFormat.set24HourTimePref(is24Hour);
+ }
}
private class H extends Handler {
@@ -1152,6 +1193,7 @@ public final class ActivityThread {
public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
public static final int INSTALL_PROVIDER = 145;
+
String codeToString(int code) {
if (DEBUG_MESSAGES) {
switch (code) {
@@ -4215,6 +4257,11 @@ public final class ActivityThread {
Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory");
}
}
+
+
+ final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
+ DateFormat.set24HourTimePref(is24Hr);
+
/**
* For system applications on userdebug/eng builds, log stack
* traces of disk and network access to dropbox for analysis.
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 20198f9..f1c632e 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -630,6 +630,15 @@ public abstract class ApplicationThreadNative extends Binder
reply.writeNoException();
return true;
}
+
+ case UPDATE_TIME_PREFS_TRANSACTION:
+ {
+ data.enforceInterface(IApplicationThread.descriptor);
+ byte is24Hour = data.readByte();
+ updateTimePrefs(is24Hour == (byte) 1);
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -1273,4 +1282,13 @@ class ApplicationThreadProxy implements IApplicationThread {
mRemote.transact(SCHEDULE_INSTALL_PROVIDER_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
data.recycle();
}
+
+ @Override
+ public void updateTimePrefs(boolean is24Hour) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(IApplicationThread.descriptor);
+ data.writeByte(is24Hour ? (byte) 1 : (byte) 0);
+ mRemote.transact(UPDATE_TIME_PREFS_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+ data.recycle();
+ }
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 1ea9d87..ac8ac8f 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -139,6 +139,7 @@ public interface IApplicationThread extends IInterface {
throws RemoteException;
void setProcessState(int state) throws RemoteException;
void scheduleInstallProvider(ProviderInfo provider) throws RemoteException;
+ void updateTimePrefs(boolean is24Hour) throws RemoteException;
String descriptor = "android.app.IApplicationThread";
@@ -192,4 +193,5 @@ public interface IApplicationThread extends IInterface {
int SCHEDULE_TRANSLUCENT_CONVERSION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+48;
int SET_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+49;
int SCHEDULE_INSTALL_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+50;
+ int UPDATE_TIME_PREFS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+51;
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index cd1fbf6..12a8ff6 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -612,6 +612,13 @@ public class Notification implements Parcelable
public static final String EXTRA_AS_HEADS_UP = "headsup";
/**
+ * Extra added from {@link Notification.Builder} to indicate that the remote views were inflated
+ * from the builder, as opposed to being created directly from the application.
+ * @hide
+ */
+ public static final String EXTRA_BUILDER_REMOTE_VIEWS = "android.builderRemoteViews";
+
+ /**
* Value for {@link #EXTRA_AS_HEADS_UP}.
* @hide
*/
@@ -1273,6 +1280,7 @@ public class Notification implements Parcelable
private boolean mShowWhen = true;
private int mVisibility = VISIBILITY_PRIVATE;
private Notification mPublicVersion = null;
+ private boolean mQuantumTheme;
/**
* Constructs a new Builder with the defaults:
@@ -1300,6 +1308,9 @@ public class Notification implements Parcelable
mWhen = System.currentTimeMillis();
mAudioStreamType = STREAM_DEFAULT;
mPriority = PRIORITY_DEFAULT;
+
+ // TODO: Decide on targetSdk from calling app whether to use quantum theme.
+ mQuantumTheme = true;
}
/**
@@ -1807,7 +1818,7 @@ public class Notification implements Parcelable
contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
smallIconImageViewId = R.id.right_icon;
}
- if (mPriority < PRIORITY_LOW) {
+ if (!mQuantumTheme && mPriority < PRIORITY_LOW) {
contentView.setInt(R.id.icon,
"setBackgroundResource", R.drawable.notification_template_icon_low_bg);
contentView.setInt(R.id.status_bar_latest_event_content,
@@ -1921,7 +1932,7 @@ public class Notification implements Parcelable
if (mContentView != null) {
return mContentView;
} else {
- return applyStandardTemplate(R.layout.notification_template_base, true); // no more special large_icon flavor
+ return applyStandardTemplate(getBaseLayoutResource(), true); // no more special large_icon flavor
}
}
@@ -1942,21 +1953,21 @@ public class Notification implements Parcelable
private RemoteViews makeBigContentView() {
if (mActions.size() == 0) return null;
- return applyStandardTemplateWithActions(R.layout.notification_template_big_base);
+ return applyStandardTemplateWithActions(getBigBaseLayoutResource());
}
- private RemoteViews makeHEadsUpContentView() {
+ private RemoteViews makeHeadsUpContentView() {
if (mActions.size() == 0) return null;
- return applyStandardTemplateWithActions(R.layout.notification_template_big_base);
+ return applyStandardTemplateWithActions(getBigBaseLayoutResource());
}
private RemoteViews generateActionButton(Action action) {
final boolean tombstone = (action.actionIntent == null);
RemoteViews button = new RemoteViews(mContext.getPackageName(),
- tombstone ? R.layout.notification_action_tombstone
- : R.layout.notification_action);
+ tombstone ? getActionTombstoneLayoutResource()
+ : getActionLayoutResource());
button.setTextViewCompoundDrawablesRelative(R.id.action0, action.icon, 0, 0, 0);
button.setTextViewText(R.id.action0, action.title);
if (!tombstone) {
@@ -1992,7 +2003,7 @@ public class Notification implements Parcelable
n.defaults = mDefaults;
n.flags = mFlags;
n.bigContentView = makeBigContentView();
- n.headsUpContentView = makeHEadsUpContentView();
+ n.headsUpContentView = makeHeadsUpContentView();
if (mLedOnMs != 0 || mLedOffMs != 0) {
n.flags |= FLAG_SHOW_LIGHTS;
}
@@ -2037,6 +2048,7 @@ public class Notification implements Parcelable
extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate);
extras.putBoolean(EXTRA_SHOW_CHRONOMETER, mUseChronometer);
extras.putBoolean(EXTRA_SHOW_WHEN, mShowWhen);
+ extras.putBoolean(EXTRA_BUILDER_REMOTE_VIEWS, mContentView == null);
if (mLargeIcon != null) {
extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon);
}
@@ -2080,6 +2092,49 @@ public class Notification implements Parcelable
build().cloneInto(n, true);
return n;
}
+
+
+ private int getBaseLayoutResource() {
+ return mQuantumTheme
+ ? R.layout.notification_template_quantum_base
+ : R.layout.notification_template_base;
+ }
+
+ private int getBigBaseLayoutResource() {
+ return mQuantumTheme
+ ? R.layout.notification_template_quantum_big_base
+ : R.layout.notification_template_big_base;
+ }
+
+ private int getBigPictureLayoutResource() {
+ return mQuantumTheme
+ ? R.layout.notification_template_quantum_big_picture
+ : R.layout.notification_template_big_picture;
+ }
+
+ private int getBigTextLayoutResource() {
+ return mQuantumTheme
+ ? R.layout.notification_template_quantum_big_text
+ : R.layout.notification_template_big_text;
+ }
+
+ private int getInboxLayoutResource() {
+ return mQuantumTheme
+ ? R.layout.notification_template_quantum_inbox
+ : R.layout.notification_template_inbox;
+ }
+
+ private int getActionLayoutResource() {
+ return mQuantumTheme
+ ? R.layout.notification_quantum_action
+ : R.layout.notification_action;
+ }
+
+ private int getActionTombstoneLayoutResource() {
+ return mQuantumTheme
+ ? R.layout.notification_quantum_action_tombstone
+ : R.layout.notification_action_tombstone;
+ }
}
/**
@@ -2249,7 +2304,7 @@ public class Notification implements Parcelable
}
private RemoteViews makeBigContentView() {
- RemoteViews contentView = getStandardView(R.layout.notification_template_big_picture);
+ RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource());
contentView.setImageViewBitmap(R.id.big_picture, mPicture);
@@ -2348,7 +2403,7 @@ public class Notification implements Parcelable
final boolean hadThreeLines = (mBuilder.mContentText != null && mBuilder.mSubText != null);
mBuilder.mContentText = null;
- RemoteViews contentView = getStandardView(R.layout.notification_template_big_text);
+ RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource());
if (hadThreeLines) {
// vertical centering
@@ -2442,7 +2497,7 @@ public class Notification implements Parcelable
private RemoteViews makeBigContentView() {
// Remove the content text so line3 disappears unless you have a summary
mBuilder.mContentText = null;
- RemoteViews contentView = getStandardView(R.layout.notification_template_inbox);
+ RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource());
contentView.setViewVisibility(R.id.text2, View.GONE);
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index b8b8f5f..333f825 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -79,6 +79,13 @@ public final class BluetoothInputDevice implements BluetoothProfile {
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_HANDSHAKE =
+ "android.bluetooth.input.profile.action.HANDSHAKE";
+
+ /**
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_REPORT =
"android.bluetooth.input.profile.action.REPORT";
@@ -185,6 +192,11 @@ public final class BluetoothInputDevice implements BluetoothProfile {
/**
* @hide
*/
+ public static final String EXTRA_STATUS = "android.bluetooth.BluetoothInputDevice.extra.STATUS";
+
+ /**
+ * @hide
+ */
public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS";
private Context mContext;
@@ -608,7 +620,7 @@ public final class BluetoothInputDevice implements BluetoothProfile {
* @hide
*/
public boolean setReport(BluetoothDevice device, byte reportType, String report) {
- if (DBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
+ if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
if (mService != null && isEnabled() && isValidDevice(device)) {
try {
return mService.setReport(device, reportType, report);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3fdb6e7..f0b7ca8 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3334,6 +3334,15 @@ public class Intent implements Parcelable, Cloneable {
public static final String EXTRA_SHUTDOWN_USERSPACE_ONLY
= "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
+ /**
+ * Optional boolean extra for {@link #ACTION_TIME_CHANGED} that indicates the
+ * user has set their time format preferences to the 24 hour format.
+ *
+ * @hide for internal use only.
+ */
+ public static final String EXTRA_TIME_PREF_24_HOUR_FORMAT =
+ "android.intent.extra.TIME_PREF_24_HOUR_FORMAT";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Intent flags (see mFlags variable).
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 2893522..419abf2 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -315,6 +315,24 @@ public class ColorStateList implements Parcelable {
return mDefaultColor;
}
+ /**
+ * Return the states in this {@link ColorStateList}.
+ * @return the states in this {@link ColorStateList}
+ * @hide
+ */
+ public int[][] getStates() {
+ return mStateSpecs;
+ }
+
+ /**
+ * Return the colors in this {@link ColorStateList}.
+ * @return the colors in this {@link ColorStateList}
+ * @hide
+ */
+ public int[] getColors() {
+ return mColors;
+ }
+
@Override
public String toString() {
return "ColorStateList{" +
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index da6ae56..5c27072 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1625,7 +1625,7 @@ public class Resources {
String locale = null;
if (mConfiguration.locale != null) {
- locale = localeToLanguageTag(mConfiguration.locale);
+ locale = adjustLanguageTag(localeToLanguageTag(mConfiguration.locale));
}
int width, height;
if (mMetrics.widthPixels >= mMetrics.heightPixels) {
@@ -1713,6 +1713,41 @@ public class Resources {
}
/**
+ * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
+ * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
+ *
+ * All released versions of android prior to "L" used the deprecated language
+ * tags, so we will need to support them for backwards compatibility.
+ *
+ * Note that this conversion needs to take place *after* the call to
+ * {@code toLanguageTag} because that will convert all the deprecated codes to
+ * the new ones, even if they're set manually.
+ */
+ private static String adjustLanguageTag(String languageTag) {
+ final int separator = languageTag.indexOf('-');
+ final String language;
+ final String remainder;
+
+ if (separator == -1) {
+ language = languageTag;
+ remainder = "";
+ } else {
+ language = languageTag.substring(0, separator);
+ remainder = languageTag.substring(separator);
+ }
+
+ if ("id".equals(language)) {
+ return "in" + remainder;
+ } else if ("yi".equals(language)) {
+ return "ji" + remainder;
+ } else if ("he".equals(language)) {
+ return "iw" + remainder;
+ } else {
+ return languageTag;
+ }
+ }
+
+ /**
* Update the system resources configuration if they have previously
* been initialized.
*
diff --git a/core/java/android/net/CaptivePortalTracker.java b/core/java/android/net/CaptivePortalTracker.java
index 5b6f154..89c17c7 100644
--- a/core/java/android/net/CaptivePortalTracker.java
+++ b/core/java/android/net/CaptivePortalTracker.java
@@ -421,6 +421,13 @@ public class CaptivePortalTracker extends StateMachine {
case ConnectivityManager.TYPE_WIFI:
WifiInfo currentWifiInfo = mWifiManager.getConnectionInfo();
if (currentWifiInfo != null) {
+ // NOTE: getSSID()'s behavior changed in API 17; before that, SSIDs were not
+ // surrounded by double quotation marks (thus violating the Javadoc), but this
+ // was changed to match the Javadoc in API 17. Since clients may have started
+ // sanitizing the output of this method since API 17 was released, we should
+ // not change it here as it would become impossible to tell whether the SSID is
+ // simply being surrounded by quotes due to the API, or whether those quotes
+ // are actually part of the SSID.
latencyBroadcast.putExtra(EXTRA_SSID, currentWifiInfo.getSSID());
latencyBroadcast.putExtra(EXTRA_BSSID, currentWifiInfo.getBSSID());
} else {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index cc4bb51..0da77ea 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -578,6 +578,9 @@ public abstract class BatteryStats implements Parcelable {
// The wake lock that was acquired at this point.
public HistoryTag wakelockTag;
+ // Kernel wakeup reason at this point.
+ public HistoryTag wakeReasonTag;
+
public static final int EVENT_FLAG_START = 0x8000;
public static final int EVENT_FLAG_FINISH = 0x4000;
@@ -612,6 +615,7 @@ public abstract class BatteryStats implements Parcelable {
// Pre-allocated objects.
public final HistoryTag localWakelockTag = new HistoryTag();
+ public final HistoryTag localWakeReasonTag = new HistoryTag();
public final HistoryTag localEventTag = new HistoryTag();
public HistoryItem() {
@@ -645,6 +649,12 @@ public abstract class BatteryStats implements Parcelable {
} else {
dest.writeInt(0);
}
+ if (wakeReasonTag != null) {
+ dest.writeInt(1);
+ wakeReasonTag.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
dest.writeInt(eventCode);
if (eventCode != EVENT_NONE) {
dest.writeInt(eventCode);
@@ -670,6 +680,12 @@ public abstract class BatteryStats implements Parcelable {
} else {
wakelockTag = null;
}
+ if (src.readInt() != 0) {
+ wakeReasonTag = localWakeReasonTag;
+ wakeReasonTag.readFromParcel(src);
+ } else {
+ wakeReasonTag = null;
+ }
eventCode = src.readInt();
if (eventCode != EVENT_NONE) {
eventTag = localEventTag;
@@ -689,6 +705,7 @@ public abstract class BatteryStats implements Parcelable {
batteryVoltage = 0;
states = 0;
wakelockTag = null;
+ wakeReasonTag = null;
eventCode = EVENT_NONE;
eventTag = null;
}
@@ -719,6 +736,12 @@ public abstract class BatteryStats implements Parcelable {
} else {
wakelockTag = null;
}
+ if (o.wakeReasonTag != null) {
+ wakeReasonTag = localWakeReasonTag;
+ wakeReasonTag.setTo(o.wakeReasonTag);
+ } else {
+ wakeReasonTag = null;
+ }
eventCode = o.eventCode;
if (o.eventTag != null) {
eventTag = localEventTag;
@@ -750,6 +773,14 @@ public abstract class BatteryStats implements Parcelable {
return false;
}
}
+ if (wakeReasonTag != o.wakeReasonTag) {
+ if (wakeReasonTag == null || o.wakeReasonTag == null) {
+ return false;
+ }
+ if (!wakeReasonTag.equals(o.wakeReasonTag)) {
+ return false;
+ }
+ }
if (eventTag != o.eventTag) {
if (eventTag == null || o.eventTag == null) {
return false;
@@ -1916,51 +1947,6 @@ public abstract class BatteryStats implements Parcelable {
long fullWakeLockTimeTotalMicros = 0;
long partialWakeLockTimeTotalMicros = 0;
- final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
- @Override
- public int compare(TimerEntry lhs, TimerEntry rhs) {
- long lhsTime = lhs.mTime;
- long rhsTime = rhs.mTime;
- if (lhsTime < rhsTime) {
- return 1;
- }
- if (lhsTime > rhsTime) {
- return -1;
- }
- return 0;
- }
- };
-
- if (reqUid < 0) {
- Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
- if (kernelWakelocks.size() > 0) {
- final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
- for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
- BatteryStats.Timer timer = ent.getValue();
- long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
- if (totalTimeMillis > 0) {
- timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
- }
- }
- Collections.sort(timers, timerComparator);
- for (int i=0; i<timers.size(); i++) {
- TimerEntry timer = timers.get(i);
- String linePrefix = ": ";
- sb.setLength(0);
- sb.append(prefix);
- sb.append(" Kernel Wake lock ");
- sb.append(timer.mName);
- linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null,
- which, linePrefix);
- if (!linePrefix.equals(": ")) {
- sb.append(" realtime");
- // Only print out wake locks that were held
- pw.println(sb.toString());
- }
- }
- }
- }
-
final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
for (int iu = 0; iu < NU; iu++) {
@@ -2292,6 +2278,55 @@ public abstract class BatteryStats implements Parcelable {
pw.println();
}
+ final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
+ @Override
+ public int compare(TimerEntry lhs, TimerEntry rhs) {
+ long lhsTime = lhs.mTime;
+ long rhsTime = rhs.mTime;
+ if (lhsTime < rhsTime) {
+ return 1;
+ }
+ if (lhsTime > rhsTime) {
+ return -1;
+ }
+ return 0;
+ }
+ };
+
+ if (reqUid < 0) {
+ Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
+ if (kernelWakelocks.size() > 0) {
+ final ArrayList<TimerEntry> ktimers = new ArrayList<TimerEntry>();
+ for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
+ BatteryStats.Timer timer = ent.getValue();
+ long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
+ if (totalTimeMillis > 0) {
+ ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
+ }
+ }
+ if (ktimers.size() > 0) {
+ Collections.sort(ktimers, timerComparator);
+ pw.print(prefix); pw.println(" All kernel wake locks:");
+ for (int i=0; i<ktimers.size(); i++) {
+ TimerEntry timer = ktimers.get(i);
+ String linePrefix = ": ";
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Kernel Wake lock ");
+ sb.append(timer.mName);
+ linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null,
+ which, linePrefix);
+ if (!linePrefix.equals(": ")) {
+ sb.append(" realtime");
+ // Only print out wake locks that were held
+ pw.println(sb.toString());
+ }
+ }
+ pw.println();
+ }
+ }
+ }
+
if (timers.size() > 0) {
Collections.sort(timers, timerComparator);
pw.print(prefix); pw.println(" All partial wake locks:");
@@ -2727,14 +2762,22 @@ public abstract class BatteryStats implements Parcelable {
public void printNextItem(PrintWriter pw, HistoryItem rec, long now, boolean checkin) {
if (!checkin) {
pw.print(" ");
- TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
+ if (now >= 0) {
+ TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
+ } else {
+ TimeUtils.formatDuration(rec.time, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
+ }
pw.print(" (");
pw.print(rec.numReadInts);
pw.print(") ");
} else {
if (lastTime < 0) {
- pw.print("@");
- pw.print(rec.time-now);
+ if (now >= 0) {
+ pw.print("@");
+ pw.print(rec.time-now);
+ } else {
+ pw.print(rec.time);
+ }
} else {
pw.print(rec.time-lastTime);
}
@@ -2858,6 +2901,18 @@ public abstract class BatteryStats implements Parcelable {
}
printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
HISTORY_STATE_DESCRIPTIONS, !checkin);
+ if (rec.wakeReasonTag != null) {
+ if (checkin) {
+ pw.print(",Wr=");
+ pw.print(rec.wakeReasonTag.poolIdx);
+ } else {
+ pw.print(" wake_reason=");
+ pw.print(rec.wakeReasonTag.uid);
+ pw.print(":\"");
+ pw.print(rec.wakeReasonTag.string);
+ pw.print("\"");
+ }
+ }
if (rec.eventCode != HistoryItem.EVENT_NONE) {
pw.print(checkin ? "," : " ");
if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
@@ -2918,108 +2973,130 @@ public abstract class BatteryStats implements Parcelable {
pw.print(suffix);
}
+ public static final int DUMP_UNPLUGGED_ONLY = 1<<0;
+ public static final int DUMP_CHARGED_ONLY = 1<<1;
+ public static final int DUMP_HISTORY_ONLY = 1<<2;
+ public static final int DUMP_INCLUDE_HISTORY = 1<<3;
+
/**
* Dumps a human-readable summary of the battery statistics to the given PrintWriter.
*
* @param pw a Printer to receive the dump output.
*/
@SuppressWarnings("unused")
- public void dumpLocked(Context context, PrintWriter pw, boolean isUnpluggedOnly, int reqUid,
- boolean historyOnly) {
+ public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
prepareForDumpLocked();
- long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
+ final boolean filtering =
+ (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
- final HistoryItem rec = new HistoryItem();
- final long historyTotalSize = getHistoryTotalSize();
- final long historyUsedSize = getHistoryUsedSize();
- if (startIteratingHistoryLocked()) {
- try {
- pw.print("Battery History (");
- pw.print((100*historyUsedSize)/historyTotalSize);
- pw.print("% used, ");
- printSizeValue(pw, historyUsedSize);
- pw.print(" used of ");
- printSizeValue(pw, historyTotalSize);
- pw.print(", ");
- pw.print(getHistoryStringPoolSize());
- pw.print(" strings using ");
- printSizeValue(pw, getHistoryStringPoolBytes());
- pw.println("):");
- HistoryPrinter hprinter = new HistoryPrinter();
- while (getNextHistoryLocked(rec)) {
- hprinter.printNextItem(pw, rec, now, false);
+ if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
+ long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
+
+ final HistoryItem rec = new HistoryItem();
+ final long historyTotalSize = getHistoryTotalSize();
+ final long historyUsedSize = getHistoryUsedSize();
+ if (startIteratingHistoryLocked()) {
+ try {
+ pw.print("Battery History (");
+ pw.print((100*historyUsedSize)/historyTotalSize);
+ pw.print("% used, ");
+ printSizeValue(pw, historyUsedSize);
+ pw.print(" used of ");
+ printSizeValue(pw, historyTotalSize);
+ pw.print(", ");
+ pw.print(getHistoryStringPoolSize());
+ pw.print(" strings using ");
+ printSizeValue(pw, getHistoryStringPoolBytes());
+ pw.println("):");
+ HistoryPrinter hprinter = new HistoryPrinter();
+ long lastTime = -1;
+ while (getNextHistoryLocked(rec)) {
+ lastTime = rec.time;
+ if (rec.time >= histStart) {
+ hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, false);
+ }
+ }
+ if (histStart >= 0) {
+ pw.print(" NEXT: "); pw.println(lastTime+1);
+ }
+ pw.println();
+ } finally {
+ finishIteratingHistoryLocked();
}
- pw.println();
- } finally {
- finishIteratingHistoryLocked();
}
- }
- if (startIteratingOldHistoryLocked()) {
- try {
- pw.println("Old battery History:");
- HistoryPrinter hprinter = new HistoryPrinter();
- while (getNextOldHistoryLocked(rec)) {
- hprinter.printNextItem(pw, rec, now, false);
+ if (startIteratingOldHistoryLocked()) {
+ try {
+ pw.println("Old battery History:");
+ HistoryPrinter hprinter = new HistoryPrinter();
+ while (getNextOldHistoryLocked(rec)) {
+ hprinter.printNextItem(pw, rec, now, false);
+ }
+ pw.println();
+ } finally {
+ finishIteratingOldHistoryLocked();
}
- pw.println();
- } finally {
- finishIteratingOldHistoryLocked();
}
}
- if (historyOnly) {
+ if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) == 0) {
return;
}
- SparseArray<? extends Uid> uidStats = getUidStats();
- final int NU = uidStats.size();
- boolean didPid = false;
- long nowRealtime = SystemClock.elapsedRealtime();
- for (int i=0; i<NU; i++) {
- Uid uid = uidStats.valueAt(i);
- SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
- if (pids != null) {
- for (int j=0; j<pids.size(); j++) {
- Uid.Pid pid = pids.valueAt(j);
- if (!didPid) {
- pw.println("Per-PID Stats:");
- didPid = true;
+ if (!filtering) {
+ SparseArray<? extends Uid> uidStats = getUidStats();
+ final int NU = uidStats.size();
+ boolean didPid = false;
+ long nowRealtime = SystemClock.elapsedRealtime();
+ for (int i=0; i<NU; i++) {
+ Uid uid = uidStats.valueAt(i);
+ SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
+ if (pids != null) {
+ for (int j=0; j<pids.size(); j++) {
+ Uid.Pid pid = pids.valueAt(j);
+ if (!didPid) {
+ pw.println("Per-PID Stats:");
+ didPid = true;
+ }
+ long time = pid.mWakeSum + (pid.mWakeStart != 0
+ ? (nowRealtime - pid.mWakeStart) : 0);
+ pw.print(" PID "); pw.print(pids.keyAt(j));
+ pw.print(" wake time: ");
+ TimeUtils.formatDuration(time, pw);
+ pw.println("");
}
- long time = pid.mWakeSum + (pid.mWakeStart != 0
- ? (nowRealtime - pid.mWakeStart) : 0);
- pw.print(" PID "); pw.print(pids.keyAt(j));
- pw.print(" wake time: ");
- TimeUtils.formatDuration(time, pw);
- pw.println("");
}
}
- }
- if (didPid) {
- pw.println("");
+ if (didPid) {
+ pw.println("");
+ }
}
- if (!isUnpluggedOnly) {
+ if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
pw.println("Statistics since last charge:");
pw.println(" System starts: " + getStartCount()
+ ", currently on battery: " + getIsOnBattery());
dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid);
pw.println("");
}
- pw.println("Statistics since last unplugged:");
- dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid);
+ if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
+ pw.println("Statistics since last unplugged:");
+ dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid);
+ }
}
@SuppressWarnings("unused")
- public void dumpCheckinLocked(Context context,
- PrintWriter pw, List<ApplicationInfo> apps, boolean isUnpluggedOnly,
- boolean includeHistory, boolean historyOnly) {
+ public void dumpCheckinLocked(Context context, PrintWriter pw,
+ List<ApplicationInfo> apps, int flags, long histStart) {
prepareForDumpLocked();
long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
- if (includeHistory || historyOnly) {
+ final boolean filtering =
+ (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
+
+ if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
final HistoryItem rec = new HistoryItem();
if (startIteratingHistoryLocked()) {
try {
@@ -3034,10 +3111,17 @@ public abstract class BatteryStats implements Parcelable {
pw.println();
}
HistoryPrinter hprinter = new HistoryPrinter();
+ long lastTime = -1;
while (getNextHistoryLocked(rec)) {
- pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
- pw.print(HISTORY_DATA); pw.print(',');
- hprinter.printNextItem(pw, rec, now, true);
+ lastTime = rec.time;
+ if (rec.time >= histStart) {
+ pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+ pw.print(HISTORY_DATA); pw.print(',');
+ hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, true);
+ }
+ }
+ if (histStart >= 0) {
+ pw.print("NEXT: "); pw.println(lastTime+1);
}
} finally {
finishIteratingHistoryLocked();
@@ -3045,7 +3129,7 @@ public abstract class BatteryStats implements Parcelable {
}
}
- if (historyOnly) {
+ if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) == 0) {
return;
}
@@ -3076,11 +3160,10 @@ public abstract class BatteryStats implements Parcelable {
}
}
}
- if (isUnpluggedOnly) {
- dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
- }
- else {
+ if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
+ }
+ if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
}
}
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 9f1e72d..c88b4c0 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -28,6 +28,7 @@ import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOverlay;
+import android.view.WindowId;
import android.widget.ListView;
import android.widget.Spinner;
@@ -496,7 +497,8 @@ public abstract class Transition implements Cloneable {
view = (start != null) ? start.view : null;
}
if (animator != null) {
- AnimationInfo info = new AnimationInfo(view, getName(), infoValues);
+ AnimationInfo info = new AnimationInfo(view, getName(),
+ sceneRoot.getWindowId(), infoValues);
runningAnimators.put(animator, info);
mAnimators.add(animator);
}
@@ -1199,13 +1201,17 @@ public abstract class Transition implements Cloneable {
*
* @hide
*/
- public void pause() {
+ public void pause(View sceneRoot) {
if (!mEnded) {
ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
int numOldAnims = runningAnimators.size();
+ WindowId windowId = sceneRoot.getWindowId();
for (int i = numOldAnims - 1; i >= 0; i--) {
- Animator anim = runningAnimators.keyAt(i);
- anim.pause();
+ AnimationInfo info = runningAnimators.valueAt(i);
+ if (info.view != null && windowId.equals(info.windowId)) {
+ Animator anim = runningAnimators.keyAt(i);
+ anim.pause();
+ }
}
if (mListeners != null && mListeners.size() > 0) {
ArrayList<TransitionListener> tmpListeners =
@@ -1226,14 +1232,18 @@ public abstract class Transition implements Cloneable {
*
* @hide
*/
- public void resume() {
+ public void resume(View sceneRoot) {
if (mPaused) {
if (!mEnded) {
ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
int numOldAnims = runningAnimators.size();
+ WindowId windowId = sceneRoot.getWindowId();
for (int i = numOldAnims - 1; i >= 0; i--) {
- Animator anim = runningAnimators.keyAt(i);
- anim.resume();
+ AnimationInfo info = runningAnimators.valueAt(i);
+ if (info.view != null && windowId.equals(info.windowId)) {
+ Animator anim = runningAnimators.keyAt(i);
+ anim.resume();
+ }
}
if (mListeners != null && mListeners.size() > 0) {
ArrayList<TransitionListener> tmpListeners =
@@ -1644,11 +1654,13 @@ public abstract class Transition implements Cloneable {
public View view;
String name;
TransitionValues values;
+ WindowId windowId;
- AnimationInfo(View view, String name, TransitionValues values) {
+ AnimationInfo(View view, String name, WindowId windowId, TransitionValues values) {
this.view = view;
this.name = name;
this.values = values;
+ this.windowId = windowId;
}
}
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index f3abfb0..1614d34 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -302,7 +302,7 @@ public class TransitionManager {
ArrayList<Transition> runningTransitions = getRunningTransitions().get(mSceneRoot);
if (runningTransitions != null && runningTransitions.size() > 0) {
for (Transition runningTransition : runningTransitions) {
- runningTransition.resume();
+ runningTransition.resume(mSceneRoot);
}
}
mTransition.clearValues(true);
@@ -335,7 +335,7 @@ public class TransitionManager {
mTransition.captureValues(mSceneRoot, false);
if (previousRunningTransitions != null) {
for (Transition runningTransition : previousRunningTransitions) {
- runningTransition.resume();
+ runningTransition.resume(mSceneRoot);
}
}
mTransition.playTransition(mSceneRoot);
@@ -351,7 +351,7 @@ public class TransitionManager {
if (runningTransitions != null && runningTransitions.size() > 0) {
for (Transition runningTransition : runningTransitions) {
- runningTransition.pause();
+ runningTransition.pause(sceneRoot);
}
}
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index 4545e3b..19d6b3d 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -317,21 +317,21 @@ public class TransitionSet extends Transition {
/** @hide */
@Override
- public void pause() {
- super.pause();
+ public void pause(View sceneRoot) {
+ super.pause(sceneRoot);
int numTransitions = mTransitions.size();
for (int i = 0; i < numTransitions; ++i) {
- mTransitions.get(i).pause();
+ mTransitions.get(i).pause(sceneRoot);
}
}
/** @hide */
@Override
- public void resume() {
- super.resume();
+ public void resume(View sceneRoot) {
+ super.resume(sceneRoot);
int numTransitions = mTransitions.size();
for (int i = 0; i < numTransitions; ++i) {
- mTransitions.get(i).resume();
+ mTransitions.get(i).resume(sceneRoot);
}
}
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 7e745d8..c183f08 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -628,11 +628,19 @@ public class KeyEvent extends InputEvent implements Parcelable {
/** Key code constant: Brightness Up key.
* Adjusts the screen brightness up. */
public static final int KEYCODE_BRIGHTNESS_UP = 221;
- /** Key code constant: Audio Track key
+ /** Key code constant: Audio Track key.
* Switches the audio tracks. */
public static final int KEYCODE_MEDIA_AUDIO_TRACK = 222;
+ /** Key code constant: Sleep key.
+ * Puts the device to sleep. Behaves somewhat like {@link #KEYCODE_POWER} but it
+ * has no effect if the device is already asleep. */
+ public static final int KEYCODE_SLEEP = 223;
+ /** Key code constant: Wakeup key.
+ * Wakes up the device. Behaves somewhat like {@link #KEYCODE_POWER} but it
+ * has no effect if the device is already awake. */
+ public static final int KEYCODE_WAKEUP = 224;
- private static final int LAST_KEYCODE = KEYCODE_MEDIA_AUDIO_TRACK;
+ private static final int LAST_KEYCODE = KEYCODE_WAKEUP;
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
@@ -877,6 +885,8 @@ public class KeyEvent extends InputEvent implements Parcelable {
names.append(KEYCODE_BRIGHTNESS_DOWN, "KEYCODE_BRIGHTNESS_DOWN");
names.append(KEYCODE_BRIGHTNESS_UP, "KEYCODE_BRIGHTNESS_UP");
names.append(KEYCODE_MEDIA_AUDIO_TRACK, "KEYCODE_MEDIA_AUDIO_TRACK");
+ names.append(KEYCODE_SLEEP, "KEYCODE_SLEEP");
+ names.append(KEYCODE_WAKEUP, "KEYCODE_WAKEUP");
};
// Symbolic names of all metakeys in bit order from least significant to most significant.
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 9b23b35..1f211c2 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -255,8 +255,9 @@ public class SurfaceView extends View {
updateWindow(false, false);
}
+ /** @hide */
@Override
- protected void onDetachedFromWindow() {
+ protected void onDetachedFromWindowInternal() {
if (mGlobalListenersAdded) {
ViewTreeObserver observer = getViewTreeObserver();
observer.removeOnScrollChangedListener(mScrollChangedListener);
@@ -278,7 +279,7 @@ public class SurfaceView extends View {
mSession = null;
mLayout.token = null;
- super.onDetachedFromWindow();
+ super.onDetachedFromWindowInternal();
}
@Override
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index ef0d80d..3cfe5e9 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -228,10 +228,11 @@ public class TextureView extends View {
}
}
+ /** @hide */
@Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
+ protected void onDetachedFromWindowInternal() {
destroySurface();
+ super.onDetachedFromWindowInternal();
}
private void destroySurface() {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a57b311..9b45f97 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8705,7 +8705,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* <p>When implementing this, you probably also want to implement
* {@link #onCheckIsTextEditor()} to indicate you will return a
- * non-null InputConnection.
+ * non-null InputConnection.</p>
+ *
+ * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
+ * object correctly and in its entirety, so that the connected IME can rely
+ * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
+ * and {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
+ * must be filled in with the correct cursor position for IMEs to work correctly
+ * with your application.</p>
*
* @param outAttrs Fill in with attribute information about the connection.
*/
@@ -10838,11 +10845,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Sets the outline of the view, which defines the shape of the shadow it
* casts, and can used for clipping.
* <p>
+ * The outline path of a View must be {@link android.graphics.Path#isConvex() convex}.
+ * <p>
* If the outline is not set, or {@link Path#isEmpty()}, shadows will be
* cast from the bounds of the View, and clipToOutline will be ignored.
*
- * @param outline The new outline of the view. Must be non-null.
+ * @param outline The new outline of the view. Must be non-null, and convex.
*
+ * @see #setCastsShadow(boolean)
* @see #getOutline(Path)
* @see #getClipToOutline()
* @see #setClipToOutline(boolean)
@@ -10851,6 +10861,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (outline == null) {
throw new IllegalArgumentException("Path must be non-null");
}
+ if (!outline.isConvex()) {
+ throw new IllegalArgumentException("Path must be convex");
+ }
// always copy the path since caller may reuse
if (mOutline == null) {
mOutline = new Path(outline);
@@ -10921,9 +10934,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Set to true to enable this View to cast shadows.
* <p>
* If enabled, and the View has a z translation greater than 0, or is
- * rotated in 3D, the shadow will be cast onto the current
- * {@link ViewGroup#setIsolatedZVolume(boolean) isolated Z volume},
- * at the z = 0 plane.
+ * rotated in 3D, the shadow will be cast onto its parent at the z = 0
+ * plane.
* <p>
* The shape of the shadow being cast is defined by the
* {@link #setOutline(Path) outline} of the view, or the rectangular bounds
@@ -13110,6 +13122,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #onAttachedToWindow()
*/
protected void onDetachedFromWindow() {
+ }
+
+ /**
+ * This is a framework-internal mirror of onDetachedFromWindow() that's called
+ * after onDetachedFromWindow().
+ *
+ * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
+ * The super method should be called at the end of the overriden method to ensure
+ * subclasses are destroyed first
+ *
+ * @hide
+ */
+ protected void onDetachedFromWindowInternal() {
mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
@@ -13297,6 +13322,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
onDetachedFromWindow();
+ onDetachedFromWindowInternal();
ListenerInfo li = mListenerInfo;
final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9c50323..f9b9401 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3166,6 +3166,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @see #setIsolatedZVolume(boolean)
*
* @return True if the ViewGroup has an isolated Z volume.
+ *
+ * @hide
*/
public boolean hasIsolatedZVolume() {
return ((mGroupFlags & FLAG_ISOLATED_Z_VOLUME) != 0);
@@ -3180,6 +3182,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* ordering space, false if its decendents should inhabit the
* inherited Z ordering volume.
* @attr ref android.R.styleable#ViewGroup_isolatedZVolume
+ *
+ * @hide
*/
public void setIsolatedZVolume(boolean isolateZVolume) {
boolean previousValue = (mGroupFlags & FLAG_ISOLATED_Z_VOLUME) != 0;
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index d4e005b..c0395cf 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -26,13 +26,13 @@ import android.util.Printer;
/**
* An EditorInfo describes several attributes of a text editing object
* that an input method is communicating with (typically an EditText), most
- * importantly the type of text content it contains.
+ * importantly the type of text content it contains and the current cursor position.
*/
public class EditorInfo implements InputType, Parcelable {
/**
* The content type of the text box, whose bits are defined by
* {@link InputType}.
- *
+ *
* @see InputType
* @see #TYPE_MASK_CLASS
* @see #TYPE_MASK_VARIATION
@@ -47,55 +47,55 @@ public class EditorInfo implements InputType, Parcelable {
* to provide alternative mechanisms for providing that command.
*/
public static final int IME_MASK_ACTION = 0x000000ff;
-
+
/**
* Bits of {@link #IME_MASK_ACTION}: no specific action has been
* associated with this editor, let the editor come up with its own if
* it can.
*/
public static final int IME_ACTION_UNSPECIFIED = 0x00000000;
-
+
/**
* Bits of {@link #IME_MASK_ACTION}: there is no available action.
*/
public static final int IME_ACTION_NONE = 0x00000001;
-
+
/**
* Bits of {@link #IME_MASK_ACTION}: the action key performs a "go"
* operation to take the user to the target of the text they typed.
* Typically used, for example, when entering a URL.
*/
public static final int IME_ACTION_GO = 0x00000002;
-
+
/**
* Bits of {@link #IME_MASK_ACTION}: the action key performs a "search"
* operation, taking the user to the results of searching for the text
* they have typed (in whatever context is appropriate).
*/
public static final int IME_ACTION_SEARCH = 0x00000003;
-
+
/**
* Bits of {@link #IME_MASK_ACTION}: the action key performs a "send"
* operation, delivering the text to its target. This is typically used
* when composing a message in IM or SMS where sending is immediate.
*/
public static final int IME_ACTION_SEND = 0x00000004;
-
+
/**
* Bits of {@link #IME_MASK_ACTION}: the action key performs a "next"
* operation, taking the user to the next field that will accept text.
*/
public static final int IME_ACTION_NEXT = 0x00000005;
-
+
/**
* Bits of {@link #IME_MASK_ACTION}: the action key performs a "done"
* operation, typically meaning there is nothing more to input and the
* IME will be closed.
*/
public static final int IME_ACTION_DONE = 0x00000006;
-
+
/**
- * Bits of {@link #IME_MASK_ACTION}: Like {@link #IME_ACTION_NEXT}, but
+ * Bits of {@link #IME_MASK_ACTION}: like {@link #IME_ACTION_NEXT}, but
* for moving to the previous field. This will normally not be used to
* specify an action (since it precludes {@link #IME_ACTION_NEXT}), but
* can be returned to the app if it sets {@link #IME_FLAG_NAVIGATE_PREVIOUS}.
@@ -154,7 +154,7 @@ public class EditorInfo implements InputType, Parcelable {
* on older versions of the platform.
*/
public static final int IME_FLAG_NO_EXTRACT_UI = 0x10000000;
-
+
/**
* Flag of {@link #imeOptions}: used in conjunction with one of the actions
* masked by {@link #IME_MASK_ACTION}, this indicates that the action
@@ -167,7 +167,7 @@ public class EditorInfo implements InputType, Parcelable {
* to show more text.
*/
public static final int IME_FLAG_NO_ACCESSORY_ACTION = 0x20000000;
-
+
/**
* Flag of {@link #imeOptions}: used in conjunction with one of the actions
* masked by {@link #IME_MASK_ACTION}. If this flag is not set, IMEs will
@@ -202,13 +202,13 @@ public class EditorInfo implements InputType, Parcelable {
* Generic unspecified type for {@link #imeOptions}.
*/
public static final int IME_NULL = 0x00000000;
-
+
/**
* Extended type information for the editor, to help the IME better
* integrate with it.
*/
public int imeOptions = IME_NULL;
-
+
/**
* A string supplying additional information options that are
* private to a particular IME implementation. The string must be
@@ -221,7 +221,7 @@ public class EditorInfo implements InputType, Parcelable {
* attribute of a TextView.
*/
public String privateImeOptions = null;
-
+
/**
* In some cases an IME may be able to display an arbitrary label for
* a command the user can perform, which you can specify here. This is
@@ -233,7 +233,7 @@ public class EditorInfo implements InputType, Parcelable {
* ignore this.
*/
public CharSequence actionLabel = null;
-
+
/**
* If {@link #actionLabel} has been given, this is the id for that command
* when the user presses its button that is delivered back with
@@ -241,50 +241,66 @@ public class EditorInfo implements InputType, Parcelable {
* InputConnection.performEditorAction()}.
*/
public int actionId = 0;
-
+
/**
* The text offset of the start of the selection at the time editing
- * began; -1 if not known. Keep in mind some IMEs may not be able
- * to give their full feature set without knowing the cursor position;
- * avoid passing -1 here if you can.
+ * begins; -1 if not known. Keep in mind that, without knowing the cursor
+ * position, many IMEs will not be able to offer their full feature set and
+ * may even behave in unpredictable ways: pass the actual cursor position
+ * here if possible at all.
+ *
+ * <p>Also, this needs to be the cursor position <strong>right now</strong>,
+ * not at some point in the past, even if input is starting in the same text field
+ * as before. When the app is filling this object, input is about to start by
+ * definition, and this value will override any value the app may have passed to
+ * {@link InputMethodManager#updateSelection(android.view.View, int, int, int, int)}
+ * before.</p>
*/
public int initialSelStart = -1;
-
+
/**
- * The text offset of the end of the selection at the time editing
- * began; -1 if not known. Keep in mind some IMEs may not be able
- * to give their full feature set without knowing the cursor position;
- * avoid passing -1 here if you can.
+ * <p>The text offset of the end of the selection at the time editing
+ * begins; -1 if not known. Keep in mind that, without knowing the cursor
+ * position, many IMEs will not be able to offer their full feature set and
+ * may behave in unpredictable ways: pass the actual cursor position
+ * here if possible at all.</p>
+ *
+ * <p>Also, this needs to be the cursor position <strong>right now</strong>,
+ * not at some point in the past, even if input is starting in the same text field
+ * as before. When the app is filling this object, input is about to start by
+ * definition, and this value will override any value the app may have passed to
+ * {@link InputMethodManager#updateSelection(android.view.View, int, int, int, int)}
+ * before.</p>
*/
public int initialSelEnd = -1;
-
+
/**
* The capitalization mode of the first character being edited in the
* text. Values may be any combination of
* {@link TextUtils#CAP_MODE_CHARACTERS TextUtils.CAP_MODE_CHARACTERS},
* {@link TextUtils#CAP_MODE_WORDS TextUtils.CAP_MODE_WORDS}, and
* {@link TextUtils#CAP_MODE_SENTENCES TextUtils.CAP_MODE_SENTENCES}, though
- * you should generally just take a non-zero value to mean start out in
- * caps mode.
+ * you should generally just take a non-zero value to mean "start out in
+ * caps mode".
*/
public int initialCapsMode = 0;
-
+
/**
* The "hint" text of the text view, typically shown in-line when the
* text is empty to tell the user what to enter.
*/
public CharSequence hintText;
-
+
/**
* A label to show to the user describing the text they are writing.
*/
public CharSequence label;
-
+
/**
* Name of the package that owns this editor.
*/
public String packageName;
-
+
/**
* Identifier for the editor's field. This is optional, and may be
* 0. By default it is filled in with the result of
@@ -292,14 +308,14 @@ public class EditorInfo implements InputType, Parcelable {
* is being edited.
*/
public int fieldId;
-
+
/**
* Additional name for the editor's field. This can supply additional
* name information for the field. By default it is null. The actual
* contents have no meaning.
*/
public String fieldName;
-
+
/**
* Any extra data to supply to the input method. This is for extended
* communication with specific input methods; the name fields in the
@@ -309,7 +325,7 @@ public class EditorInfo implements InputType, Parcelable {
* attribute of a TextView.
*/
public Bundle extras;
-
+
/**
* Ensure that the data in this EditorInfo is compatible with an application
* that was developed against the given target API version. This can
@@ -365,10 +381,10 @@ public class EditorInfo implements InputType, Parcelable {
+ " fieldName=" + fieldName);
pw.println(prefix + "extras=" + extras);
}
-
+
/**
* Used to package this object into a {@link Parcel}.
- *
+ *
* @param dest The {@link Parcel} to be written.
* @param flags The flags used for parceling.
*/
@@ -392,30 +408,31 @@ public class EditorInfo implements InputType, Parcelable {
/**
* Used to make this class parcelable.
*/
- public static final Parcelable.Creator<EditorInfo> CREATOR = new Parcelable.Creator<EditorInfo>() {
- public EditorInfo createFromParcel(Parcel source) {
- EditorInfo res = new EditorInfo();
- res.inputType = source.readInt();
- res.imeOptions = source.readInt();
- res.privateImeOptions = source.readString();
- res.actionLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- res.actionId = source.readInt();
- res.initialSelStart = source.readInt();
- res.initialSelEnd = source.readInt();
- res.initialCapsMode = source.readInt();
- res.hintText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- res.label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- res.packageName = source.readString();
- res.fieldId = source.readInt();
- res.fieldName = source.readString();
- res.extras = source.readBundle();
- return res;
- }
+ public static final Parcelable.Creator<EditorInfo> CREATOR =
+ new Parcelable.Creator<EditorInfo>() {
+ public EditorInfo createFromParcel(Parcel source) {
+ EditorInfo res = new EditorInfo();
+ res.inputType = source.readInt();
+ res.imeOptions = source.readInt();
+ res.privateImeOptions = source.readString();
+ res.actionLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+ res.actionId = source.readInt();
+ res.initialSelStart = source.readInt();
+ res.initialSelEnd = source.readInt();
+ res.initialCapsMode = source.readInt();
+ res.hintText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+ res.label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+ res.packageName = source.readString();
+ res.fieldId = source.readInt();
+ res.fieldName = source.readString();
+ res.extras = source.readBundle();
+ return res;
+ }
- public EditorInfo[] newArray(int size) {
- return new EditorInfo[size];
- }
- };
+ public EditorInfo[] newArray(int size) {
+ return new EditorInfo[size];
+ }
+ };
public int describeContents() {
return 0;
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 9f2bf33..f8160c8 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -37,6 +37,7 @@ import android.util.Printer;
import android.util.Slog;
import android.util.Xml;
import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
+import android.view.inputmethod.InputMethodSubtypeArray;
import java.io.IOException;
import java.util.ArrayList;
@@ -86,9 +87,9 @@ public final class InputMethodInfo implements Parcelable {
final int mIsDefaultResId;
/**
- * The array of the subtypes.
+ * An array-like container of the subtypes.
*/
- private final ArrayList<InputMethodSubtype> mSubtypes = new ArrayList<InputMethodSubtype>();
+ private final InputMethodSubtypeArray mSubtypes;
private final boolean mIsAuxIme;
@@ -138,6 +139,7 @@ public final class InputMethodInfo implements Parcelable {
int isDefaultResId = 0;
XmlResourceParser parser = null;
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
try {
parser = si.loadXmlMetaData(pm, InputMethod.SERVICE_META_DATA);
if (parser == null) {
@@ -206,7 +208,7 @@ public final class InputMethodInfo implements Parcelable {
if (!subtype.isAuxiliary()) {
isAuxIme = false;
}
- mSubtypes.add(subtype);
+ subtypes.add(subtype);
}
}
} catch (NameNotFoundException e) {
@@ -216,7 +218,7 @@ public final class InputMethodInfo implements Parcelable {
if (parser != null) parser.close();
}
- if (mSubtypes.size() == 0) {
+ if (subtypes.size() == 0) {
isAuxIme = false;
}
@@ -225,14 +227,15 @@ public final class InputMethodInfo implements Parcelable {
final int N = additionalSubtypes.size();
for (int i = 0; i < N; ++i) {
final InputMethodSubtype subtype = additionalSubtypes.get(i);
- if (!mSubtypes.contains(subtype)) {
- mSubtypes.add(subtype);
+ if (!subtypes.contains(subtype)) {
+ subtypes.add(subtype);
} else {
Slog.w(TAG, "Duplicated subtype definition found: "
+ subtype.getLocale() + ", " + subtype.getMode());
}
}
}
+ mSubtypes = new InputMethodSubtypeArray(subtypes);
mSettingsActivityName = settingsActivityComponent;
mIsDefaultResId = isDefaultResId;
mIsAuxIme = isAuxIme;
@@ -246,7 +249,7 @@ public final class InputMethodInfo implements Parcelable {
mIsAuxIme = source.readInt() == 1;
mSupportsSwitchingToNextInputMethod = source.readInt() == 1;
mService = ResolveInfo.CREATOR.createFromParcel(source);
- source.readTypedList(mSubtypes, InputMethodSubtype.CREATOR);
+ mSubtypes = new InputMethodSubtypeArray(source);
mForceDefault = false;
}
@@ -272,9 +275,7 @@ public final class InputMethodInfo implements Parcelable {
mSettingsActivityName = settingsActivity;
mIsDefaultResId = isDefaultResId;
mIsAuxIme = isAuxIme;
- if (subtypes != null) {
- mSubtypes.addAll(subtypes);
- }
+ mSubtypes = new InputMethodSubtypeArray(subtypes);
mForceDefault = forceDefault;
mSupportsSwitchingToNextInputMethod = true;
}
@@ -364,7 +365,7 @@ public final class InputMethodInfo implements Parcelable {
* composed of {@link #getPackageName} and the class name returned here.
*
* <p>A null will be returned if there is no settings activity associated
- * with the input method.
+ * with the input method.</p>
*/
public String getSettingsActivity() {
return mSettingsActivityName;
@@ -374,7 +375,7 @@ public final class InputMethodInfo implements Parcelable {
* Return the count of the subtypes of Input Method.
*/
public int getSubtypeCount() {
- return mSubtypes.size();
+ return mSubtypes.getCount();
}
/**
@@ -479,7 +480,7 @@ public final class InputMethodInfo implements Parcelable {
dest.writeInt(mIsAuxIme ? 1 : 0);
dest.writeInt(mSupportsSwitchingToNextInputMethod ? 1 : 0);
mService.writeToParcel(dest, flags);
- dest.writeTypedList(mSubtypes);
+ mSubtypes.writeToParcel(dest);
}
/**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 70c53d2..e812edd 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1394,6 +1394,14 @@ public final class InputMethodManager {
/**
* Report the current selection range.
+ *
+ * <p><strong>Editor authors</strong>, you need to call this method whenever
+ * the cursor moves in your editor. Remember that in addition to doing this, your
+ * editor needs to always supply current cursor values in
+ * {@link EditorInfo#initialSelStart} and {@link EditorInfo#initialSelEnd} every
+ * time {@link android.view.View#onCreateInputConnection(EditorInfo)} is
+ * called, which happens whenever the keyboard shows up or the focus changes
+ * to a text field, among other cases.</p>
*/
public void updateSelection(View view, int selStart, int selEnd,
int candidatesStart, int candidatesEnd) {
diff --git a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
new file mode 100644
index 0000000..5bef71f
--- /dev/null
+++ b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2007-2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.view.inputmethod;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AndroidRuntimeException;
+import android.util.Slog;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * An array-like container that stores multiple instances of {@link InputMethodSubtype}.
+ *
+ * <p>This container is designed to reduce the risk of {@link TransactionTooLargeException}
+ * when one or more instancess of {@link InputMethodInfo} are transferred through IPC.
+ * Basically this class does following three tasks.</p>
+ * <ul>
+ * <li>Applying compression for the marshalled data</li>
+ * <li>Lazily unmarshalling objects</li>
+ * <li>Caching the marshalled data when appropriate</li>
+ * </ul>
+ *
+ * @hide
+ */
+public class InputMethodSubtypeArray {
+ private final static String TAG = "InputMethodSubtypeArray";
+
+ /**
+ * Create a new instance of {@link InputMethodSubtypeArray} from an existing list of
+ * {@link InputMethodSubtype}.
+ *
+ * @param subtypes A list of {@link InputMethodSubtype} from which
+ * {@link InputMethodSubtypeArray} will be created.
+ */
+ public InputMethodSubtypeArray(final List<InputMethodSubtype> subtypes) {
+ if (subtypes == null) {
+ mCount = 0;
+ return;
+ }
+ mCount = subtypes.size();
+ mInstance = subtypes.toArray(new InputMethodSubtype[mCount]);
+ }
+
+ /**
+ * Unmarshall an instance of {@link InputMethodSubtypeArray} from a given {@link Parcel}
+ * object.
+ *
+ * @param source A {@link Parcel} object from which {@link InputMethodSubtypeArray} will be
+ * unmarshalled.
+ */
+ public InputMethodSubtypeArray(final Parcel source) {
+ mCount = source.readInt();
+ if (mCount > 0) {
+ mDecompressedSize = source.readInt();
+ mCompressedData = source.createByteArray();
+ }
+ }
+
+ /**
+ * Marshall the instance into a given {@link Parcel} object.
+ *
+ * <p>This methods may take a bit additional time to compress data lazily when called
+ * first time.</p>
+ *
+ * @param source A {@link Parcel} object to which {@link InputMethodSubtypeArray} will be
+ * marshalled.
+ */
+ public void writeToParcel(final Parcel dest) {
+ if (mCount == 0) {
+ dest.writeInt(mCount);
+ return;
+ }
+
+ byte[] compressedData = mCompressedData;
+ int decompressedSize = mDecompressedSize;
+ if (compressedData == null && decompressedSize == 0) {
+ synchronized (mLockObject) {
+ compressedData = mCompressedData;
+ decompressedSize = mDecompressedSize;
+ if (compressedData == null && decompressedSize == 0) {
+ final byte[] decompressedData = marshall(mInstance);
+ compressedData = compress(decompressedData);
+ if (compressedData == null) {
+ decompressedSize = -1;
+ Slog.i(TAG, "Failed to compress data.");
+ } else {
+ decompressedSize = decompressedData.length;
+ }
+ mDecompressedSize = decompressedSize;
+ mCompressedData = compressedData;
+ }
+ }
+ }
+
+ if (compressedData != null && decompressedSize > 0) {
+ dest.writeInt(mCount);
+ dest.writeInt(decompressedSize);
+ dest.writeByteArray(compressedData);
+ } else {
+ Slog.i(TAG, "Unexpected state. Behaving as an empty array.");
+ dest.writeInt(0);
+ }
+ }
+
+ /**
+ * Return {@link InputMethodSubtype} specified with the given index.
+ *
+ * <p>This methods may take a bit additional time to decompress data lazily when called
+ * first time.</p>
+ *
+ * @param index The index of {@link InputMethodSubtype}.
+ */
+ public InputMethodSubtype get(final int index) {
+ if (index < 0 || mCount <= index) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ InputMethodSubtype[] instance = mInstance;
+ if (instance == null) {
+ synchronized (mLockObject) {
+ instance = mInstance;
+ if (instance == null) {
+ final byte[] decompressedData =
+ decompress(mCompressedData, mDecompressedSize);
+ // Clear the compressed data until {@link #getMarshalled()} is called.
+ mCompressedData = null;
+ mDecompressedSize = 0;
+ if (decompressedData != null) {
+ instance = unmarshall(decompressedData);
+ } else {
+ Slog.e(TAG, "Failed to decompress data. Returns null as fallback.");
+ instance = new InputMethodSubtype[mCount];
+ }
+ mInstance = instance;
+ }
+ }
+ }
+ return instance[index];
+ }
+
+ /**
+ * Return the number of {@link InputMethodSubtype} objects.
+ */
+ public int getCount() {
+ return mCount;
+ }
+
+ private final Object mLockObject = new Object();
+ private final int mCount;
+
+ private volatile InputMethodSubtype[] mInstance;
+ private volatile byte[] mCompressedData;
+ private volatile int mDecompressedSize;
+
+ private static byte[] marshall(final InputMethodSubtype[] array) {
+ Parcel parcel = null;
+ try {
+ parcel = Parcel.obtain();
+ parcel.writeTypedArray(array, 0);
+ return parcel.marshall();
+ } finally {
+ if (parcel != null) {
+ parcel.recycle();
+ parcel = null;
+ }
+ }
+ }
+
+ private static InputMethodSubtype[] unmarshall(final byte[] data) {
+ Parcel parcel = null;
+ try {
+ parcel = Parcel.obtain();
+ parcel.unmarshall(data, 0, data.length);
+ parcel.setDataPosition(0);
+ return parcel.createTypedArray(InputMethodSubtype.CREATOR);
+ } finally {
+ if (parcel != null) {
+ parcel.recycle();
+ parcel = null;
+ }
+ }
+ }
+
+ private static byte[] compress(final byte[] data) {
+ ByteArrayOutputStream resultStream = null;
+ GZIPOutputStream zipper = null;
+ try {
+ resultStream = new ByteArrayOutputStream();
+ zipper = new GZIPOutputStream(resultStream);
+ zipper.write(data);
+ } catch(IOException e) {
+ return null;
+ } finally {
+ try {
+ if (zipper != null) {
+ zipper.close();
+ }
+ } catch (IOException e) {
+ zipper = null;
+ Slog.e(TAG, "Failed to close the stream.", e);
+ // swallowed, not propagated back to the caller
+ }
+ try {
+ if (resultStream != null) {
+ resultStream.close();
+ }
+ } catch (IOException e) {
+ resultStream = null;
+ Slog.e(TAG, "Failed to close the stream.", e);
+ // swallowed, not propagated back to the caller
+ }
+ }
+ return resultStream != null ? resultStream.toByteArray() : null;
+ }
+
+ private static byte[] decompress(final byte[] data, final int expectedSize) {
+ ByteArrayInputStream inputStream = null;
+ GZIPInputStream unzipper = null;
+ try {
+ inputStream = new ByteArrayInputStream(data);
+ unzipper = new GZIPInputStream(inputStream);
+ final byte [] result = new byte[expectedSize];
+ int totalReadBytes = 0;
+ while (totalReadBytes < result.length) {
+ final int restBytes = result.length - totalReadBytes;
+ final int readBytes = unzipper.read(result, totalReadBytes, restBytes);
+ if (readBytes < 0) {
+ break;
+ }
+ totalReadBytes += readBytes;
+ }
+ if (expectedSize != totalReadBytes) {
+ return null;
+ }
+ return result;
+ } catch(IOException e) {
+ return null;
+ } finally {
+ try {
+ if (unzipper != null) {
+ unzipper.close();
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close the stream.", e);
+ // swallowed, not propagated back to the caller
+ }
+ try {
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close the stream.", e);
+ // swallowed, not propagated back to the caller
+ }
+ }
+ }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 826bcec..81d36a4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2139,10 +2139,11 @@ public class WebView extends AbsoluteLayout
mProvider.getViewDelegate().onAttachedToWindow();
}
+ /** @hide */
@Override
- protected void onDetachedFromWindow() {
+ protected void onDetachedFromWindowInternal() {
mProvider.getViewDelegate().onDetachedFromWindow();
- super.onDetachedFromWindow();
+ super.onDetachedFromWindowInternal();
}
@Override
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 47d42dc..96a2ab5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2135,15 +2135,15 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mRecycler.markChildrenDirty();
}
- // TODO: Move somewhere sane. This doesn't belong in onLayout().
- if (mFastScroll != null) {
- mFastScroll.onItemCountChanged(childCount, mItemCount);
- }
-
layoutChildren();
mInLayout = false;
mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;
+
+ // TODO: Move somewhere sane. This doesn't belong in onLayout().
+ if (mFastScroll != null) {
+ mFastScroll.onItemCountChanged(getChildCount(), mItemCount);
+ }
}
/**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index e5cb16f..687036c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4729,10 +4729,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mEditor != null) mEditor.onAttachedToWindow();
}
+ /** @hide */
@Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
+ protected void onDetachedFromWindowInternal() {
if (mPreDrawRegistered) {
getViewTreeObserver().removeOnPreDrawListener(this);
mPreDrawRegistered = false;
@@ -4741,6 +4740,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
resetResolvedDrawables();
if (mEditor != null) mEditor.onDetachedFromWindow();
+
+ super.onDetachedFromWindowInternal();
}
@Override
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index fd93604..db21906 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -87,7 +87,7 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 97 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 98 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -1712,7 +1712,7 @@ public final class BatteryStatsImpl extends BatteryStats {
static final int DELTA_STATE_FLAG = 0x00100000;
// Flag in delta int: a new full state2 int follows.
static final int DELTA_STATE2_FLAG = 0x00200000;
- // Flag in delta int: contains a wakelock tag.
+ // Flag in delta int: contains a wakelock or wakeReason tag.
static final int DELTA_WAKELOCK_FLAG = 0x00400000;
// Flag in delta int: contains an event description.
static final int DELTA_EVENT_FLAG = 0x00800000;
@@ -1759,7 +1759,7 @@ public final class BatteryStatsImpl extends BatteryStats {
if (stateIntChanged) {
firstToken |= DELTA_STATE_FLAG;
}
- if (cur.wakelockTag != null) {
+ if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
firstToken |= DELTA_WAKELOCK_FLAG;
}
if (cur.eventCode != HistoryItem.EVENT_NONE) {
@@ -1795,11 +1795,24 @@ public final class BatteryStatsImpl extends BatteryStats {
+ " batteryPlugType=" + cur.batteryPlugType
+ " states=0x" + Integer.toHexString(cur.states));
}
- if (cur.wakelockTag != null) {
- int index = writeHistoryTag(cur.wakelockTag);
- dest.writeInt(index);
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
- + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
+ if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
+ int wakeLockIndex;
+ int wakeReasonIndex;
+ if (cur.wakelockTag != null) {
+ wakeLockIndex = writeHistoryTag(cur.wakelockTag);
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
+ + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
+ } else {
+ wakeLockIndex = 0xffff;
+ }
+ if (cur.wakeReasonTag != null) {
+ wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
+ + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
+ } else {
+ wakeReasonIndex = 0xffff;
+ }
+ dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
}
if (cur.eventCode != HistoryItem.EVENT_NONE) {
int index = writeHistoryTag(cur.eventTag);
@@ -1905,14 +1918,29 @@ public final class BatteryStatsImpl extends BatteryStats {
}
if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
- cur.wakelockTag = cur.localWakelockTag;
- int index = src.readInt();
- readHistoryTag(index, cur.wakelockTag);
+ int indexes = src.readInt();
+ int wakeLockIndex = indexes&0xffff;
+ int wakeReasonIndex = (indexes>>16)&0xffff;
+ if (wakeLockIndex != 0xffff) {
+ cur.wakelockTag = cur.localWakelockTag;
+ readHistoryTag(wakeLockIndex, cur.wakelockTag);
+ if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
+ + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
+ } else {
+ cur.wakelockTag = null;
+ }
+ if (wakeReasonIndex != 0xffff) {
+ cur.wakeReasonTag = cur.localWakeReasonTag;
+ readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
+ if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
+ + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
+ } else {
+ cur.wakeReasonTag = null;
+ }
cur.numReadInts += 1;
- if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
- + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
} else {
cur.wakelockTag = null;
+ cur.wakeReasonTag = null;
}
if ((firstToken&DELTA_EVENT_FLAG) != 0) {
@@ -1944,6 +1972,7 @@ public final class BatteryStatsImpl extends BatteryStats {
if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
&& timeDiff < 1000 && (diffStates&lastDiffStates) == 0
&& (mHistoryLastWritten.wakelockTag == null || mHistoryCur.wakelockTag == null)
+ && (mHistoryLastWritten.wakeReasonTag == null || mHistoryCur.wakeReasonTag == null)
&& (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
|| mHistoryCur.eventCode == HistoryItem.EVENT_NONE)
&& mHistoryLastWritten.batteryLevel == mHistoryCur.batteryLevel
@@ -1968,6 +1997,13 @@ public final class BatteryStatsImpl extends BatteryStats {
mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
mHistoryCur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
}
+ // If the last written history had a wake reason tag, we need to retain it.
+ // Note that the condition above made sure that we aren't in a case where
+ // both it and the current history item have a wakelock tag.
+ if (mHistoryLastWritten.wakeReasonTag != null) {
+ mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
+ mHistoryCur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
+ }
// If the last written history had an event, we need to retain it.
// Note that the condition above made sure that we aren't in a case where
// both it and the current history item have an event.
@@ -2016,6 +2052,7 @@ public final class BatteryStatsImpl extends BatteryStats {
writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
mLastHistoryTime = curTime;
mHistoryCur.wakelockTag = null;
+ mHistoryCur.wakeReasonTag = null;
mHistoryCur.eventCode = HistoryItem.EVENT_NONE;
mHistoryCur.eventTag = null;
if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
@@ -2304,6 +2341,16 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ public void noteWakeupReasonLocked(int irq, String reason) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason irq #" + irq + "\"" + reason +"\": "
+ + Integer.toHexString(mHistoryCur.states));
+ mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
+ mHistoryCur.wakeReasonTag.string = reason;
+ mHistoryCur.wakeReasonTag.uid = irq;
+ addHistoryRecordLocked(elapsedRealtime);
+ }
+
public int startAddingCpuLocked() {
mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
@@ -7219,8 +7266,7 @@ public final class BatteryStatsImpl extends BatteryStats {
pullPendingStateUpdatesLocked();
}
- public void dumpLocked(Context context, PrintWriter pw, boolean isUnpluggedOnly, int reqUid,
- boolean historyOnly) {
+ public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
if (DEBUG) {
pw.println("mOnBatteryTimeBase:");
mOnBatteryTimeBase.dump(pw, " ");
@@ -7264,6 +7310,6 @@ public final class BatteryStatsImpl extends BatteryStats {
mBluetoothStateTimer[i].logState(pr, " ");
}
}
- super.dumpLocked(context, pw, isUnpluggedOnly, reqUid, historyOnly);
+ super.dumpLocked(context, pw, flags, reqUid, histStart);
}
}
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 325a27d..e51345c 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -32,7 +32,9 @@ import com.android.internal.view.IInputMethodClient;
* this file.
*/
interface IInputMethodManager {
+ // TODO: Use ParceledListSlice instead
List<InputMethodInfo> getInputMethodList();
+ // TODO: Use ParceledListSlice instead
List<InputMethodInfo> getEnabledInputMethodList();
List<InputMethodSubtype> getEnabledInputMethodSubtypeList(in String imiId,
boolean allowsImplicitlySelectedSubtypes);
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index 9fefd00..b479cb1 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -58,7 +58,9 @@ public final class RotationPolicy {
PackageManager pm = context.getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_ACCELEROMETER)
&& pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)
- && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE);
+ && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
+ && context.getResources().getBoolean(
+ com.android.internal.R.bool.config_supportAutoRotation);
}
/**
@@ -184,6 +186,7 @@ public final class RotationPolicy {
*/
public static abstract class RotationPolicyListener {
final ContentObserver mObserver = new ContentObserver(new Handler()) {
+ @Override
public void onChange(boolean selfChange, Uri uri) {
RotationPolicyListener.this.onChange();
}