diff options
Diffstat (limited to 'core/java/android')
35 files changed, 547 insertions, 465 deletions
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index e6c2a0f..61a12ee 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -445,7 +445,10 @@ public final class AnimatorSet extends Animator { // First, clear out the old listeners ArrayList<AnimatorListener> oldListeners = node.animation.getListeners(); if (oldListeners != null && oldListeners.size() > 0) { - for (AnimatorListener listener : oldListeners) { + final ArrayList<AnimatorListener> clonedListeners = new + ArrayList<AnimatorListener>(oldListeners); + + for (AnimatorListener listener : clonedListeners) { if (listener instanceof DependencyListener || listener instanceof AnimatorSetListener) { node.animation.removeListener(listener); diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 371e7ad..a8621f8 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -30,14 +30,14 @@ import android.util.AttributeSet; import android.util.DebugUtils; import android.util.SparseArray; import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; -import android.view.ContextMenu.ContextMenuInfo; import android.view.View.OnCreateContextMenuListener; +import android.view.ViewGroup; import android.widget.AdapterView; import java.io.FileDescriptor; @@ -883,8 +883,8 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene public void setHasOptionsMenu(boolean hasMenu) { if (mHasMenu != hasMenu) { mHasMenu = hasMenu; - if (isAdded() && !isHidden() && isResumed()) { - mActivity.invalidateOptionsMenu(); + if (isAdded() && !isHidden()) { + mFragmentManager.invalidateOptionsMenu(); } } } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index c33ab2c..712b55f 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -315,6 +315,12 @@ public abstract class FragmentManager { public static void enableDebugLogging(boolean enabled) { FragmentManagerImpl.DEBUG = enabled; } + + /** + * Invalidate the attached activity's options menu as necessary. + * This may end up being deferred until we move to the resumed state. + */ + public void invalidateOptionsMenu() { } } final class FragmentManagerState implements Parcelable { @@ -1816,7 +1822,16 @@ final class FragmentManagerImpl extends FragmentManager { } } } - + + @Override + public void invalidateOptionsMenu() { + if (mActivity != null && mCurState == Fragment.RESUMED) { + mActivity.invalidateOptionsMenu(); + } else { + mNeedMenuInvalidate = true; + } + } + public static int reverseTransit(int transit) { int rev = 0; switch (transit) { diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 8472b31..ff04757 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -234,14 +234,25 @@ public class WallpaperManager { } catch (OutOfMemoryError e) { Log.w(TAG, "No memory load current wallpaper", e); } - if (mWallpaper == null && returnDefault) { - mDefaultWallpaper = getDefaultWallpaperLocked(context); - return mDefaultWallpaper; + if (returnDefault) { + if (mWallpaper == null) { + mDefaultWallpaper = getDefaultWallpaperLocked(context); + return mDefaultWallpaper; + } else { + mDefaultWallpaper = null; + } } return mWallpaper; } } - + + public void forgetLoadedWallpaper() { + synchronized (this) { + mWallpaper = null; + mDefaultWallpaper = null; + } + } + private Bitmap getCurrentWallpaperLocked(Context context) { try { Bundle params = new Bundle(); @@ -402,6 +413,16 @@ public class WallpaperManager { } /** + * Remove all internal references to the last loaded wallpaper. Useful + * for apps that want to reduce memory usage when they only temporarily + * need to have the wallpaper. After calling, the next request for the + * wallpaper will require reloading it again from disk. + */ + public void forgetLoadedWallpaper() { + sGlobals.forgetLoadedWallpaper(); + } + + /** * If the current wallpaper is a live wallpaper component, return the * information about that wallpaper. Otherwise, if it is a static image, * simply return null. @@ -716,6 +737,7 @@ public class WallpaperManager { c.drawBitmap(bm, null, targetRect, paint); bm.recycle(); + c.setBitmap(null); return newbm; } catch (OutOfMemoryError e) { Log.w(TAG, "Can't generate default bitmap", e); diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java index 095cd11..316c474 100644 --- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java +++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java @@ -1048,12 +1048,12 @@ public final class BluetoothDeviceProfileState extends StateMachine { break; case CONNECT_HID_INCOMING: if (!accept) { - ret = mService.allowIncomingHidConnect(mDevice, false); + ret = mService.allowIncomingProfileConnect(mDevice, false); sendMessage(TRANSITION_TO_STABLE); updateIncomingAllowedTimer(); } else { writeTimerValue(0); - ret = mService.allowIncomingHidConnect(mDevice, true); + ret = mService.allowIncomingProfileConnect(mDevice, true); } break; default: diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java index f6757d9..282b70a 100644 --- a/core/java/android/bluetooth/BluetoothInputDevice.java +++ b/core/java/android/bluetooth/BluetoothInputDevice.java @@ -308,28 +308,6 @@ public final class BluetoothInputDevice implements BluetoothProfile { return BluetoothProfile.PRIORITY_OFF; } - /** - * Allow or disallow incoming connection - * @param device Input device - * @param allow true / false - * @return Success or Failure of the operation - * @hide - */ - public boolean allowIncomingConnect(BluetoothDevice device, boolean allow) { - if (DBG) log("allowIncomingConnect(" + device + ", " + allow + ")"); - - if (mService == null || !isEnabled() || !isValidDevice(device)) { - return false; - } - try { - mService.allowIncomingHidConnect(device, allow); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - return true; - } - private boolean isEnabled() { if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; return false; diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl index ddede9c..48dfed8 100644 --- a/core/java/android/bluetooth/IBluetooth.aidl +++ b/core/java/android/bluetooth/IBluetooth.aidl @@ -85,6 +85,7 @@ interface IBluetooth int addRfcommServiceRecord(in String serviceName, in ParcelUuid uuid, int channel, IBinder b); void removeServiceRecord(int handle); + boolean allowIncomingProfileConnect(in BluetoothDevice device, boolean value); boolean connectHeadset(String address); boolean disconnectHeadset(String address); @@ -98,7 +99,6 @@ interface IBluetooth int getInputDeviceConnectionState(in BluetoothDevice device); boolean setInputDevicePriority(in BluetoothDevice device, int priority); int getInputDevicePriority(in BluetoothDevice device); - boolean allowIncomingHidConnect(in BluetoothDevice device, boolean value); boolean isTetheringOn(); void setBluetoothTethering(boolean value); diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index b487764..6767747 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -131,7 +131,7 @@ public class Camera { private static final int CAMERA_MSG_RAW_IMAGE = 0x080; private static final int CAMERA_MSG_COMPRESSED_IMAGE = 0x100; private static final int CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x200; - private static final int CAMERA_MSG_METADATA_FACE = 0x400; + private static final int CAMERA_MSG_PREVIEW_METADATA = 0x400; private static final int CAMERA_MSG_ALL_MSGS = 0x4FF; private int mNativeContext; // accessed by native methods @@ -721,7 +721,7 @@ public class Camera { } return; - case CAMERA_MSG_METADATA_FACE: + case CAMERA_MSG_PREVIEW_METADATA: if (mFaceListener != null) { mFaceListener.onFaceDetection((Face[])msg.obj, mCamera); } @@ -1156,6 +1156,9 @@ public class Camera { * @hide */ public static class Face { + public Face() { + } + /** * Bounds of the face. (-1000, -1000) represents the top-left of the * camera field of view, and (1000, 1000) represents the bottom-right of @@ -1168,7 +1171,7 @@ public class Camera { * * @see #startFaceDetection(int) */ - Rect rect; + public Rect rect; /** * The confidence level of the face. The range is 1 to 100. 100 is the @@ -1177,32 +1180,32 @@ public class Camera { * * @see #startFaceDetection(int) */ - int score; + public int score; /** * An unique id per face while the face is visible to the tracker. If * the face leaves the field-of-view and comes back, it will get a new * id. If the value is 0, id is not supported. */ - int id; + public int id; /** * The coordinates of the center of the left eye. The range is -1000 to * 1000. null if this is not supported. */ - Point leftEye; + public Point leftEye; /** * The coordinates of the center of the right eye. The range is -1000 to * 1000. null if this is not supported. */ - Point rightEye; + public Point rightEye; /** * The coordinates of the center of the mouth. The range is -1000 to * 1000. null if this is not supported. */ - Point mouth; + public Point mouth; } // Error codes match the enum in include/ui/Camera.h @@ -1471,6 +1474,7 @@ public class Camera { "preferred-preview-size-for-video"; private static final String KEY_MAX_NUM_DETECTED_FACES_HW = "max-num-detected-faces-hw"; private static final String KEY_MAX_NUM_DETECTED_FACES_SW = "max-num-detected-faces-sw"; + private static final String KEY_RECORDING_HINT = "recording-hint"; // Parameter key suffix for supported values. private static final String SUPPORTED_VALUES_SUFFIX = "-values"; @@ -3172,6 +3176,37 @@ public class Camera { throw new IllegalArgumentException("Invalid face detection type " + type); } + /** + * Sets the hint of the recording mode. If this is true, {@link + * android.media.MediaRecorder#start()} may be faster or has less + * glitches. This should be called before starting the preview for the + * best result. But it is allowed to change the hint while the preview + * is active. The default value is false. + * + * The apps can still call {@link #takePicture(Camera.ShutterCallback, + * Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback)} + * when the hint is true. The apps can call MediaRecorder.start() when + * the hint is false. But the performance may be worse. + * + * @param hint true if the apps intend to record a video using + * {@link android.media.MediaRecorder}. + * @hide + */ + public void setRecordingHint(boolean hint) { + set(KEY_RECORDING_HINT, hint ? TRUE : FALSE); + } + + /** + * Gets the current recording hint. + * + * @return the current recording hint state. + * @see #setRecordingHint(boolean) + * @hide + */ + public boolean getRecordingHint() { + return TRUE.equals(get(KEY_RECORDING_HINT)); + } + // Splits a comma delimited string to an ArrayList of String. // Return null if the passing string is null or the size is 0. private ArrayList<String> split(String str) { diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index b548623..551926c 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -408,6 +408,23 @@ public class UsbManager { } /** + * Returns the current default USB function. + * + * @return name of the default function. + * + * {@hide} + */ + public String getDefaultFunction() { + String functions = SystemProperties.get("persist.sys.usb.config", ""); + int commaIndex = functions.indexOf(','); + if (commaIndex > 0) { + return functions.substring(0, commaIndex); + } else { + return functions; + } + } + + /** * Sets the current USB function. * If function is null, then the current function is set to the default function. * diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 0548250..c41d182 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -23,16 +23,21 @@ import android.net.NetworkTemplate; /** {@hide} */ interface INetworkStatsService { - /** Return historical stats for traffic that matches template. */ + /** Return historical network layer stats for traffic that matches template. */ NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template); - /** Return historical stats for specific UID traffic that matches template. */ + /** Return historical network layer stats for specific UID traffic that matches template. */ NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int tag); - /** Return usage summary for traffic that matches template. */ + /** Return network layer usage summary for traffic that matches template. */ NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end); - /** Return usage summary per UID for traffic that matches template. */ + /** Return network layer usage summary per UID for traffic that matches template. */ NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags); + /** Return data layer snapshot of UID network usage. */ + NetworkStats getDataLayerSnapshotForUid(int uid); + /** Increment data layer count of operations performed for UID and tag. */ + void incrementOperationCount(int uid, int tag, int operationCount); + /** Force update of statistics. */ void forceUpdate(); diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index fbff7d8..0e8e7fc 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -21,6 +21,8 @@ import android.os.Parcelable; import android.os.SystemClock; import android.util.SparseBooleanArray; +import com.android.internal.util.Objects; + import java.io.CharArrayWriter; import java.io.PrintWriter; import java.util.Arrays; @@ -56,6 +58,7 @@ public class NetworkStats implements Parcelable { private long[] rxPackets; private long[] txBytes; private long[] txPackets; + private int[] operations; public static class Entry { public String iface; @@ -65,12 +68,13 @@ public class NetworkStats implements Parcelable { public long rxPackets; public long txBytes; public long txPackets; + public int operations; public Entry() { } public Entry(String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes, - long txPackets) { + long txPackets, int operations) { this.iface = iface; this.uid = uid; this.tag = tag; @@ -78,6 +82,7 @@ public class NetworkStats implements Parcelable { this.rxPackets = rxPackets; this.txBytes = txBytes; this.txPackets = txPackets; + this.operations = operations; } } @@ -91,6 +96,7 @@ public class NetworkStats implements Parcelable { this.rxPackets = new long[initialSize]; this.txBytes = new long[initialSize]; this.txPackets = new long[initialSize]; + this.operations = new int[initialSize]; } public NetworkStats(Parcel parcel) { @@ -103,11 +109,32 @@ public class NetworkStats implements Parcelable { rxPackets = parcel.createLongArray(); txBytes = parcel.createLongArray(); txPackets = parcel.createLongArray(); + operations = parcel.createIntArray(); + } + + /** {@inheritDoc} */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(elapsedRealtime); + dest.writeInt(size); + dest.writeStringArray(iface); + dest.writeIntArray(uid); + dest.writeIntArray(tag); + dest.writeLongArray(rxBytes); + dest.writeLongArray(rxPackets); + dest.writeLongArray(txBytes); + dest.writeLongArray(txPackets); + dest.writeIntArray(operations); } public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets) { - return addValues(new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets)); + return addValues(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, 0); + } + + public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets, + long txBytes, long txPackets, int operations) { + return addValues( + new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, operations)); } /** @@ -124,6 +151,7 @@ public class NetworkStats implements Parcelable { rxPackets = Arrays.copyOf(rxPackets, newLength); txBytes = Arrays.copyOf(txBytes, newLength); txPackets = Arrays.copyOf(txPackets, newLength); + operations = Arrays.copyOf(operations, newLength); } iface[size] = entry.iface; @@ -133,6 +161,7 @@ public class NetworkStats implements Parcelable { rxPackets[size] = entry.rxPackets; txBytes[size] = entry.txBytes; txPackets[size] = entry.txPackets; + operations[size] = entry.operations; size++; return this; @@ -150,6 +179,7 @@ public class NetworkStats implements Parcelable { entry.rxPackets = rxPackets[i]; entry.txBytes = txBytes[i]; entry.txPackets = txPackets[i]; + entry.operations = operations[i]; return entry; } @@ -167,8 +197,9 @@ public class NetworkStats implements Parcelable { } public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets, - long txBytes, long txPackets) { - return combineValues(new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets)); + long txBytes, long txPackets, int operations) { + return combineValues( + new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, operations)); } /** @@ -186,6 +217,7 @@ public class NetworkStats implements Parcelable { rxPackets[i] += entry.rxPackets; txBytes[i] += entry.txBytes; txPackets[i] += entry.txPackets; + operations[i] += entry.operations; } return this; } @@ -195,7 +227,7 @@ public class NetworkStats implements Parcelable { */ public int findIndex(String iface, int uid, int tag) { for (int i = 0; i < size; i++) { - if (equal(iface, this.iface[i]) && uid == this.uid[i] && tag == this.tag[i]) { + if (Objects.equal(iface, this.iface[i]) && uid == this.uid[i] && tag == this.tag[i]) { return i; } } @@ -203,6 +235,22 @@ public class NetworkStats implements Parcelable { } /** + * Splice in {@link #operations} from the given {@link NetworkStats} based + * on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface}, + * since operation counts are at data layer. + */ + public void spliceOperationsFrom(NetworkStats stats) { + for (int i = 0; i < size; i++) { + final int j = stats.findIndex(IFACE_ALL, uid[i], tag[i]); + if (j == -1) { + operations[i] = 0; + } else { + operations[i] = stats.operations[j]; + } + } + } + + /** * Return list of unique interfaces known by this data structure. */ public String[] getUniqueIfaces() { @@ -289,15 +337,17 @@ public class NetworkStats implements Parcelable { entry.rxPackets = rxPackets[i]; entry.txBytes = txBytes[i]; entry.txPackets = txPackets[i]; + entry.operations = operations[i]; } else { // existing row, subtract remote value entry.rxBytes = rxBytes[i] - value.rxBytes[j]; entry.rxPackets = rxPackets[i] - value.rxPackets[j]; entry.txBytes = txBytes[i] - value.txBytes[j]; entry.txPackets = txPackets[i] - value.txPackets[j]; + entry.operations = operations[i] - value.operations[j]; if (enforceMonotonic && (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 - || entry.txPackets < 0)) { + || entry.txPackets < 0 || entry.operations < 0)) { throw new IllegalArgumentException("found non-monotonic values"); } if (clampNegative) { @@ -305,6 +355,7 @@ public class NetworkStats implements Parcelable { entry.rxPackets = Math.max(0, entry.rxPackets); entry.txBytes = Math.max(0, entry.txBytes); entry.txPackets = Math.max(0, entry.txPackets); + entry.operations = Math.max(0, entry.operations); } } @@ -314,10 +365,6 @@ public class NetworkStats implements Parcelable { return result; } - private static boolean equal(Object a, Object b) { - return a == b || (a != null && a.equals(b)); - } - public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime); @@ -325,11 +372,12 @@ public class NetworkStats implements Parcelable { pw.print(prefix); pw.print(" iface="); pw.print(iface[i]); pw.print(" uid="); pw.print(uid[i]); - pw.print(" tag="); pw.print(tag[i]); + pw.print(" tag=0x"); pw.print(Integer.toHexString(tag[i])); pw.print(" rxBytes="); pw.print(rxBytes[i]); pw.print(" rxPackets="); pw.print(rxPackets[i]); pw.print(" txBytes="); pw.print(txBytes[i]); - pw.print(" txPackets="); pw.println(txPackets[i]); + pw.print(" txPackets="); pw.print(txPackets[i]); + pw.print(" operations="); pw.println(operations[i]); } } @@ -345,19 +393,6 @@ public class NetworkStats implements Parcelable { return 0; } - /** {@inheritDoc} */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(elapsedRealtime); - dest.writeInt(size); - dest.writeStringArray(iface); - dest.writeIntArray(uid); - dest.writeIntArray(tag); - dest.writeLongArray(rxBytes); - dest.writeLongArray(rxPackets); - dest.writeLongArray(txBytes); - dest.writeLongArray(txPackets); - } - public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() { public NetworkStats createFromParcel(Parcel in) { return new NetworkStats(in); diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 8bd1738..4ffabb1 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -16,6 +16,16 @@ package android.net; +import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.TAG_NONE; +import static android.net.NetworkStats.UID_ALL; +import static android.net.NetworkStatsHistory.DataStreamUtils.readLongArray; +import static android.net.NetworkStatsHistory.DataStreamUtils.writeLongArray; +import static android.net.NetworkStatsHistory.ParcelUtils.readIntArray; +import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray; +import static android.net.NetworkStatsHistory.ParcelUtils.writeIntArray; +import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray; + import android.os.Parcel; import android.os.Parcelable; @@ -43,19 +53,26 @@ public class NetworkStatsHistory implements Parcelable { private static final int VERSION_INIT = 1; // TODO: teach about varint encoding to use less disk space - // TODO: extend to record rxPackets/txPackets + // TODO: teach about omitting entire fields to reduce parcel pressure + // TODO: persist/restore packet and operation counts private final long bucketDuration; private int bucketCount; private long[] bucketStart; private long[] rxBytes; + private long[] rxPackets; private long[] txBytes; + private long[] txPackets; + private int[] operations; public static class Entry { public long bucketStart; public long bucketDuration; public long rxBytes; + public long rxPackets; public long txBytes; + public long txPackets; + public int operations; } public NetworkStatsHistory(long bucketDuration) { @@ -66,15 +83,21 @@ public class NetworkStatsHistory implements Parcelable { this.bucketDuration = bucketDuration; bucketStart = new long[initialSize]; rxBytes = new long[initialSize]; + rxPackets = new long[initialSize]; txBytes = new long[initialSize]; + txPackets = new long[initialSize]; + operations = new int[initialSize]; bucketCount = 0; } public NetworkStatsHistory(Parcel in) { bucketDuration = in.readLong(); bucketStart = readLongArray(in); - rxBytes = in.createLongArray(); - txBytes = in.createLongArray(); + rxBytes = readLongArray(in); + rxPackets = readLongArray(in); + txBytes = readLongArray(in); + txPackets = readLongArray(in); + operations = readIntArray(in); bucketCount = bucketStart.length; } @@ -83,17 +106,24 @@ public class NetworkStatsHistory implements Parcelable { out.writeLong(bucketDuration); writeLongArray(out, bucketStart, bucketCount); writeLongArray(out, rxBytes, bucketCount); + writeLongArray(out, rxPackets, bucketCount); writeLongArray(out, txBytes, bucketCount); + writeLongArray(out, txPackets, bucketCount); + writeIntArray(out, operations, bucketCount); } public NetworkStatsHistory(DataInputStream in) throws IOException { + // TODO: read packet and operation counts final int version = in.readInt(); switch (version) { case VERSION_INIT: { bucketDuration = in.readLong(); bucketStart = readLongArray(in); rxBytes = readLongArray(in); + rxPackets = new long[bucketStart.length]; txBytes = readLongArray(in); + txPackets = new long[bucketStart.length]; + operations = new int[bucketStart.length]; bucketCount = bucketStart.length; break; } @@ -104,6 +134,7 @@ public class NetworkStatsHistory implements Parcelable { } public void writeToStream(DataOutputStream out) throws IOException { + // TODO: write packet and operation counts out.writeInt(VERSION_INIT); out.writeLong(bucketDuration); writeLongArray(out, bucketStart, bucketCount); @@ -148,7 +179,10 @@ public class NetworkStatsHistory implements Parcelable { entry.bucketStart = bucketStart[i]; entry.bucketDuration = bucketDuration; entry.rxBytes = rxBytes[i]; + entry.rxPackets = rxPackets[i]; entry.txBytes = txBytes[i]; + entry.txPackets = txPackets[i]; + entry.operations = operations[i]; return entry; } @@ -156,17 +190,27 @@ public class NetworkStatsHistory implements Parcelable { * Record that data traffic occurred in the given time range. Will * distribute across internal buckets, creating new buckets as needed. */ - public void recordData(long start, long end, long rx, long tx) { - if (rx < 0 || tx < 0) { - throw new IllegalArgumentException( - "tried recording negative data: rx=" + rx + ", tx=" + tx); + @Deprecated + public void recordData(long start, long end, long rxBytes, long txBytes) { + recordData(start, end, + new NetworkStats.Entry(IFACE_ALL, UID_ALL, TAG_NONE, rxBytes, 0L, txBytes, 0L, 0)); + } + + /** + * Record that data traffic occurred in the given time range. Will + * distribute across internal buckets, creating new buckets as needed. + */ + public void recordData(long start, long end, NetworkStats.Entry entry) { + if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 || entry.txPackets < 0 + || entry.operations < 0) { + throw new IllegalArgumentException("tried recording negative data"); } // create any buckets needed by this range ensureBuckets(start, end); // distribute data usage into buckets - final long duration = end - start; + long duration = end - start; for (int i = bucketCount - 1; i >= 0; i--) { final long curStart = bucketStart[i]; final long curEnd = curStart + bucketDuration; @@ -177,10 +221,22 @@ public class NetworkStatsHistory implements Parcelable { if (curStart > end) continue; final long overlap = Math.min(curEnd, end) - Math.max(curStart, start); - if (overlap > 0) { - this.rxBytes[i] += rx * overlap / duration; - this.txBytes[i] += tx * overlap / duration; - } + if (overlap <= 0) continue; + + // integer math each time is faster than floating point + final long fracRxBytes = entry.rxBytes * overlap / duration; + final long fracRxPackets = entry.rxPackets * overlap / duration; + final long fracTxBytes = entry.txBytes * overlap / duration; + final long fracTxPackets = entry.txPackets * overlap / duration; + final int fracOperations = (int) (entry.operations * overlap / duration); + + rxBytes[i] += fracRxBytes; entry.rxBytes -= fracRxBytes; + rxPackets[i] += fracRxPackets; entry.rxPackets -= fracRxPackets; + txBytes[i] += fracTxBytes; entry.txBytes -= fracTxBytes; + txPackets[i] += fracTxPackets; entry.txPackets -= fracTxPackets; + operations[i] += fracOperations; entry.operations -= fracOperations; + + duration -= overlap; } } @@ -189,10 +245,19 @@ public class NetworkStatsHistory implements Parcelable { * for combining together stats for external reporting. */ public void recordEntireHistory(NetworkStatsHistory input) { + final NetworkStats.Entry entry = new NetworkStats.Entry( + IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0); for (int i = 0; i < input.bucketCount; i++) { final long start = input.bucketStart[i]; final long end = start + input.bucketDuration; - recordData(start, end, input.rxBytes[i], input.txBytes[i]); + + entry.rxBytes = input.rxBytes[i]; + entry.rxPackets = input.rxPackets[i]; + entry.txBytes = input.txBytes[i]; + entry.txPackets = input.txPackets[i]; + entry.operations = input.operations[i]; + + recordData(start, end, entry); } } @@ -223,7 +288,10 @@ public class NetworkStatsHistory implements Parcelable { final int newLength = Math.max(bucketStart.length, 10) * 3 / 2; bucketStart = Arrays.copyOf(bucketStart, newLength); rxBytes = Arrays.copyOf(rxBytes, newLength); + rxPackets = Arrays.copyOf(rxPackets, newLength); txBytes = Arrays.copyOf(txBytes, newLength); + txPackets = Arrays.copyOf(txPackets, newLength); + operations = Arrays.copyOf(operations, newLength); } // create gap when inserting bucket in middle @@ -233,12 +301,18 @@ public class NetworkStatsHistory implements Parcelable { System.arraycopy(bucketStart, index, bucketStart, dstPos, length); System.arraycopy(rxBytes, index, rxBytes, dstPos, length); + System.arraycopy(rxPackets, index, rxPackets, dstPos, length); System.arraycopy(txBytes, index, txBytes, dstPos, length); + System.arraycopy(txPackets, index, txPackets, dstPos, length); + System.arraycopy(operations, index, operations, dstPos, length); } bucketStart[index] = start; rxBytes[index] = 0; + rxPackets[index] = 0; txBytes[index] = 0; + txPackets[index] = 0; + operations[index] = 0; bucketCount++; } @@ -260,7 +334,10 @@ public class NetworkStatsHistory implements Parcelable { final int length = bucketStart.length; bucketStart = Arrays.copyOfRange(bucketStart, i, length); rxBytes = Arrays.copyOfRange(rxBytes, i, length); + rxPackets = Arrays.copyOfRange(rxPackets, i, length); txBytes = Arrays.copyOfRange(txBytes, i, length); + txPackets = Arrays.copyOfRange(txPackets, i, length); + operations = Arrays.copyOfRange(operations, i, length); bucketCount -= i; } } @@ -282,7 +359,10 @@ public class NetworkStatsHistory implements Parcelable { entry.bucketStart = start; entry.bucketDuration = end - start; entry.rxBytes = 0; + entry.rxPackets = 0; entry.txBytes = 0; + entry.txPackets = 0; + entry.operations = 0; for (int i = bucketCount - 1; i >= 0; i--) { final long curStart = bucketStart[i]; @@ -295,14 +375,16 @@ public class NetworkStatsHistory implements Parcelable { // include full value for active buckets, otherwise only fractional final boolean activeBucket = curStart < now && curEnd > now; - final long overlap = Math.min(curEnd, end) - Math.max(curStart, start); - if (activeBucket || overlap == bucketDuration) { - entry.rxBytes += rxBytes[i]; - entry.txBytes += txBytes[i]; - } else if (overlap > 0) { - entry.rxBytes += rxBytes[i] * overlap / bucketDuration; - entry.txBytes += txBytes[i] * overlap / bucketDuration; - } + final long overlap = activeBucket ? bucketDuration + : Math.min(curEnd, end) - Math.max(curStart, start); + if (overlap <= 0) continue; + + // integer math each time is faster than floating point + entry.rxBytes += rxBytes[i] * overlap / bucketDuration; + entry.rxPackets += rxPackets[i] * overlap / bucketDuration; + entry.txBytes += txBytes[i] * overlap / bucketDuration; + entry.txPackets += txPackets[i] * overlap / bucketDuration; + entry.operations += operations[i] * overlap / bucketDuration; } return entry; @@ -315,17 +397,19 @@ public class NetworkStatsHistory implements Parcelable { public void generateRandom(long start, long end, long rx, long tx) { ensureBuckets(start, end); + final NetworkStats.Entry entry = new NetworkStats.Entry( + IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0); final Random r = new Random(); while (rx > 1024 && tx > 1024) { final long curStart = randomLong(r, start, end); final long curEnd = randomLong(r, curStart, end); - final long curRx = randomLong(r, 0, rx); - final long curTx = randomLong(r, 0, tx); + entry.rxBytes = randomLong(r, 0, rx); + entry.txBytes = randomLong(r, 0, tx); - recordData(curStart, curEnd, curRx, curTx); + recordData(curStart, curEnd, entry); - rx -= curRx; - tx -= curTx; + rx -= entry.rxBytes; + tx -= entry.txBytes; } } @@ -347,7 +431,10 @@ public class NetworkStatsHistory implements Parcelable { pw.print(prefix); pw.print(" bucketStart="); pw.print(bucketStart[i]); pw.print(" rxBytes="); pw.print(rxBytes[i]); - pw.print(" txBytes="); pw.println(txBytes[i]); + pw.print(" rxPackets="); pw.print(rxPackets[i]); + pw.print(" txBytes="); pw.print(txBytes[i]); + pw.print(" txPackets="); pw.print(txPackets[i]); + pw.print(" operations="); pw.println(operations[i]); } } @@ -368,41 +455,73 @@ public class NetworkStatsHistory implements Parcelable { } }; - private static long[] readLongArray(DataInputStream in) throws IOException { - final int size = in.readInt(); - final long[] values = new long[size]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readLong(); + /** + * Utility methods for interacting with {@link DataInputStream} and + * {@link DataOutputStream}, mostly dealing with writing partial arrays. + */ + public static class DataStreamUtils { + public static long[] readLongArray(DataInputStream in) throws IOException { + final int size = in.readInt(); + final long[] values = new long[size]; + for (int i = 0; i < values.length; i++) { + values[i] = in.readLong(); + } + return values; + } + + public static void writeLongArray(DataOutputStream out, long[] values, int size) + throws IOException { + if (size > values.length) { + throw new IllegalArgumentException("size larger than length"); + } + out.writeInt(size); + for (int i = 0; i < size; i++) { + out.writeLong(values[i]); + } } - return values; } - private static void writeLongArray(DataOutputStream out, long[] values, int size) throws IOException { - if (size > values.length) { - throw new IllegalArgumentException("size larger than length"); - } - out.writeInt(size); - for (int i = 0; i < size; i++) { - out.writeLong(values[i]); + /** + * Utility methods for interacting with {@link Parcel} structures, mostly + * dealing with writing partial arrays. + */ + public static class ParcelUtils { + public static long[] readLongArray(Parcel in) { + final int size = in.readInt(); + final long[] values = new long[size]; + for (int i = 0; i < values.length; i++) { + values[i] = in.readLong(); + } + return values; } - } - private static long[] readLongArray(Parcel in) { - final int size = in.readInt(); - final long[] values = new long[size]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readLong(); + public static void writeLongArray(Parcel out, long[] values, int size) { + if (size > values.length) { + throw new IllegalArgumentException("size larger than length"); + } + out.writeInt(size); + for (int i = 0; i < size; i++) { + out.writeLong(values[i]); + } } - return values; - } - private static void writeLongArray(Parcel out, long[] values, int size) { - if (size > values.length) { - throw new IllegalArgumentException("size larger than length"); + public static int[] readIntArray(Parcel in) { + final int size = in.readInt(); + final int[] values = new int[size]; + for (int i = 0; i < values.length; i++) { + values[i] = in.readInt(); + } + return values; } - out.writeInt(size); - for (int i = 0; i < size; i++) { - out.writeLong(values[i]); + + public static void writeIntArray(Parcel out, int[] values, int size) { + if (size > values.length) { + throw new IllegalArgumentException("size larger than length"); + } + out.writeInt(size); + for (int i = 0; i < size; i++) { + out.writeInt(values[i]); + } } } diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index e054930..f138e49 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -20,14 +20,13 @@ import android.app.DownloadManager; import android.app.backup.BackupManager; import android.content.Context; import android.media.MediaPlayer; -import android.os.IBinder; -import android.os.INetworkManagementService; import android.os.RemoteException; import android.os.ServiceManager; import com.android.server.NetworkManagementSocketTagger; import dalvik.system.SocketTagger; + import java.net.Socket; import java.net.SocketException; @@ -172,7 +171,7 @@ public class TrafficStats { } // take snapshot in time; we calculate delta later - sActiveProfilingStart = getNetworkStatsForUid(context); + sActiveProfilingStart = getDataLayerSnapshotForUid(context); } } @@ -190,7 +189,7 @@ public class TrafficStats { } // subtract starting values and return delta - final NetworkStats profilingStop = getNetworkStatsForUid(context); + final NetworkStats profilingStop = getDataLayerSnapshotForUid(context); final NetworkStats profilingDelta = profilingStop.subtractClamped( sActiveProfilingStart); sActiveProfilingStart = null; @@ -199,6 +198,28 @@ public class TrafficStats { } /** + * Increment count of network operations performed under the given + * accounting tag. This can be used to derive bytes-per-operation. + * + * @param tag Accounting tag used in {@link #setThreadStatsTag(int)}. + * @param operationCount Number of operations to increment count by. + */ + public static void incrementOperationCount(int tag, int operationCount) { + if (operationCount < 0) { + throw new IllegalArgumentException("operation count can only be incremented"); + } + + final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( + ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); + final int uid = android.os.Process.myUid(); + try { + statsService.incrementOperationCount(uid, tag, operationCount); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + /** * Get the total number of packets transmitted through the mobile interface. * * @return number of packets. If the statistics are not supported by this device, @@ -461,14 +482,12 @@ public class TrafficStats { * Return detailed {@link NetworkStats} for the current UID. Requires no * special permission. */ - private static NetworkStats getNetworkStatsForUid(Context context) { - final IBinder binder = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); - final INetworkManagementService service = INetworkManagementService.Stub.asInterface( - binder); - + private static NetworkStats getDataLayerSnapshotForUid(Context context) { + final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( + ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); final int uid = android.os.Process.myUid(); try { - return service.getNetworkStatsUidDetail(uid); + return statsService.getDataLayerSnapshotForUid(uid); } catch (RemoteException e) { throw new RuntimeException(e); } diff --git a/core/java/android/net/VpnBuilder.java b/core/java/android/net/VpnBuilder.java index 25cedb6..4582523 100644 --- a/core/java/android/net/VpnBuilder.java +++ b/core/java/android/net/VpnBuilder.java @@ -91,6 +91,7 @@ import java.util.ArrayList; * * <p class="note">Using this class requires * {@link android.Manifest.permission#VPN} permission. + * @hide */ public class VpnBuilder { diff --git a/core/java/android/nfc/ILlcpConnectionlessSocket.aidl b/core/java/android/nfc/ILlcpConnectionlessSocket.aidl deleted file mode 100644 index c6d84e5..0000000 --- a/core/java/android/nfc/ILlcpConnectionlessSocket.aidl +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.nfc; - -import android.nfc.LlcpPacket; - -/** - * @hide - */ -interface ILlcpConnectionlessSocket -{ - void close(int nativeHandle); - int getSap(int nativeHandle); - LlcpPacket receiveFrom(int nativeHandle); - int sendTo(int nativeHandle, in LlcpPacket packet); -}
\ No newline at end of file diff --git a/core/java/android/nfc/ILlcpServiceSocket.aidl b/core/java/android/nfc/ILlcpServiceSocket.aidl deleted file mode 100644 index 581c21d..0000000 --- a/core/java/android/nfc/ILlcpServiceSocket.aidl +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.nfc; - -/** - * {@hide} - */ -interface ILlcpServiceSocket -{ - int accept(int nativeHandle); - void close(int nativeHandle); -} diff --git a/core/java/android/nfc/ILlcpSocket.aidl b/core/java/android/nfc/ILlcpSocket.aidl deleted file mode 100644 index 3166e72..0000000 --- a/core/java/android/nfc/ILlcpSocket.aidl +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.nfc; - -/** - * @hide - */ -interface ILlcpSocket -{ - int close(int nativeHandle); - int connect(int nativeHandle, int sap); - int connectByName(int nativeHandle, String sn); - int getLocalSap(int nativeHandle); - int getLocalSocketMiu(int nativeHandle); - int getLocalSocketRw(int nativeHandle); - int getRemoteSocketMiu(int nativeHandle); - int getRemoteSocketRw(int nativeHandle); - int receive(int nativeHandle, out byte[] receiveBuffer); - int send(int nativeHandle, in byte[] data); -}
\ No newline at end of file diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index 2ed6619..83a055c 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -22,13 +22,8 @@ import android.content.IntentFilter; import android.nfc.NdefMessage; import android.nfc.Tag; import android.nfc.TechListParcel; -import android.nfc.ILlcpSocket; -import android.nfc.ILlcpServiceSocket; -import android.nfc.ILlcpConnectionlessSocket; import android.nfc.INdefPushCallback; import android.nfc.INfcTag; -import android.nfc.IP2pTarget; -import android.nfc.IP2pInitiator; import android.nfc.INfcAdapterExtras; /** @@ -36,12 +31,7 @@ import android.nfc.INfcAdapterExtras; */ interface INfcAdapter { - ILlcpSocket getLlcpInterface(); - ILlcpConnectionlessSocket getLlcpConnectionlessInterface(); - ILlcpServiceSocket getLlcpServiceInterface(); INfcTag getNfcTagInterface(); - IP2pTarget getP2pTargetInterface(); - IP2pInitiator getP2pInitiatorInterface(); INfcAdapterExtras getNfcAdapterExtrasInterface(); // NfcAdapter-class related methods @@ -54,10 +44,6 @@ interface INfcAdapter void disableForegroundNdefPush(in ComponentName activity); // Non-public methods - // TODO: check and complete - int createLlcpConnectionlessSocket(int sap); - int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength); - int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength); boolean disable(); boolean enable(); boolean enableZeroClick(); diff --git a/core/java/android/nfc/INfcAdapterExtras.aidl b/core/java/android/nfc/INfcAdapterExtras.aidl index 0c2a2fd..0c2a2fd 100755..100644 --- a/core/java/android/nfc/INfcAdapterExtras.aidl +++ b/core/java/android/nfc/INfcAdapterExtras.aidl diff --git a/core/java/android/nfc/IP2pInitiator.aidl b/core/java/android/nfc/IP2pInitiator.aidl deleted file mode 100644 index 931f1f8..0000000 --- a/core/java/android/nfc/IP2pInitiator.aidl +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.nfc; - -/** - * @hide - */ -interface IP2pInitiator -{ - byte[] getGeneralBytes(int nativeHandle); - int getMode(int nativeHandle); - byte[] receive(int nativeHandle); - boolean send(int nativeHandle, in byte[] data); -}
\ No newline at end of file diff --git a/core/java/android/nfc/IP2pTarget.aidl b/core/java/android/nfc/IP2pTarget.aidl deleted file mode 100644 index ddaaed42..0000000 --- a/core/java/android/nfc/IP2pTarget.aidl +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.nfc; - -/** - * @hide - */ -interface IP2pTarget -{ - byte[] getGeneralBytes(int nativeHandle); - int getMode(int nativeHandle); - int connect(int nativeHandle); - boolean disconnect(int nativeHandle); - byte[] transceive(int nativeHandle, in byte[] data); -}
\ No newline at end of file diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index d3ff8f8..a6c3387 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1445,17 +1445,16 @@ public final class Settings { public static final String VOLUME_BLUETOOTH_SCO = "volume_bluetooth_sco"; /** - * Whether the notifications should use the ring volume (value of 1) or - * a separate notification volume (value of 0). In most cases, users - * will have this enabled so the notification and ringer volumes will be - * the same. However, power users can disable this and use the separate - * notification volume control. + * Whether the notifications should use the ring volume (value of 1) or a separate + * notification volume (value of 0). In most cases, users will have this enabled so the + * notification and ringer volumes will be the same. However, power users can disable this + * and use the separate notification volume control. * <p> - * Note: This is a one-off setting that will be removed in the future - * when there is profile support. For this reason, it is kept hidden - * from the public APIs. + * Note: This is a one-off setting that will be removed in the future when there is profile + * support. For this reason, it is kept hidden from the public APIs. * * @hide + * @deprecated */ public static final String NOTIFICATIONS_USE_RING_VOLUME = "notifications_use_ring_volume"; diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java index a31374f..5217624 100644 --- a/core/java/android/provider/VoicemailContract.java +++ b/core/java/android/provider/VoicemailContract.java @@ -92,7 +92,7 @@ public class VoicemailContract { public static final String SOURCE_PACKAGE_FIELD = "source_package"; /** Defines fields exposed through the /voicemail path of this content provider. */ - public static final class Voicemails implements BaseColumns { + public static final class Voicemails implements BaseColumns, OpenableColumns { /** Not instantiable. */ private Voicemails() { } diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index 3359bf9..d73f8c9 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -54,7 +54,6 @@ class BluetoothEventLoop { private final BluetoothAdapter mAdapter; private final BluetoothAdapterStateMachine mBluetoothState; private BluetoothA2dp mA2dp; - private BluetoothInputDevice mInputDevice; private final Context mContext; // The WakeLock is used for bringing up the LCD during a pairing request // from remote device when Android is in Suspend state. @@ -134,15 +133,11 @@ class BluetoothEventLoop { public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.A2DP) { mA2dp = (BluetoothA2dp) proxy; - } else if (profile == BluetoothProfile.INPUT_DEVICE) { - mInputDevice = (BluetoothInputDevice) proxy; } } public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.A2DP) { mA2dp = null; - } else if (profile == BluetoothProfile.INPUT_DEVICE) { - mInputDevice = null; } } }; @@ -801,21 +796,25 @@ class BluetoothEventLoop { "Incoming A2DP / AVRCP connection from " + address); mA2dp.allowIncomingConnect(device, authorized); } - } else if (mInputDevice != null && BluetoothUuid.isInputDevice(uuid)) { + } else if (BluetoothUuid.isInputDevice(uuid)) { // We can have more than 1 input device connected. - authorized = mInputDevice.getPriority(device) > BluetoothInputDevice.PRIORITY_OFF; - if (authorized) { - Log.i(TAG, "First check pass for incoming HID connection from " + address); - // notify profile state change - mBluetoothService.notifyIncomingHidConnection(address); - } else { - Log.i(TAG, "Rejecting incoming HID connection from " + address); - mBluetoothService.allowIncomingHidConnect(device, authorized); - } - } else if (BluetoothUuid.isBnep(uuid) && mBluetoothService.allowIncomingTethering()){ - authorized = true; + authorized = mBluetoothService.getInputDevicePriority(device) > + BluetoothInputDevice.PRIORITY_OFF; + if (authorized) { + Log.i(TAG, "First check pass for incoming HID connection from " + address); + // notify profile state change + mBluetoothService.notifyIncomingHidConnection(address); + } else { + Log.i(TAG, "Rejecting incoming HID connection from " + address); + mBluetoothService.allowIncomingProfileConnect(device, authorized); + } + } else if (BluetoothUuid.isBnep(uuid)) { + // PAN doesn't go to the state machine, accept or reject from here + authorized = mBluetoothService.allowIncomingTethering(); + mBluetoothService.allowIncomingProfileConnect(device, authorized); } else { Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address); + mBluetoothService.allowIncomingProfileConnect(device, authorized); } log("onAgentAuthorize(" + objectPath + ", " + deviceUuid + ") = " + authorized); } diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java index 19bcd42..28546dc 100755 --- a/core/java/android/server/BluetoothService.java +++ b/core/java/android/server/BluetoothService.java @@ -2116,7 +2116,16 @@ public class BluetoothService extends IBluetooth.Stub { } } - public boolean allowIncomingHidConnect(BluetoothDevice device, boolean allow) { + /** + * Handle incoming profile acceptance for profiles handled by Bluetooth Service, + * currently PAN and HID. This also is the catch all for all rejections for profiles + * that is not supported. + * + * @param device - Bluetooth Device + * @param allow - true / false + * @return + */ + public boolean allowIncomingProfileConnect(BluetoothDevice device, boolean allow) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); String address = device.getAddress(); @@ -2126,11 +2135,11 @@ public class BluetoothService extends IBluetooth.Stub { Integer data = getAuthorizationAgentRequestData(address); if (data == null) { - Log.w(TAG, "allowIncomingHidConnect(" + device + + Log.w(TAG, "allowIncomingProfileConnect(" + device + ") called but no native data available"); return false; } - if (DBG) log("allowIncomingHidConnect: " + device + " : " + allow + " : " + data); + if (DBG) log("allowIncomingProfileConnect: " + device + " : " + allow + " : " + data); return setAuthorizationNative(address, allow, data.intValue()); } diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java index cb96969..2c78679 100644 --- a/core/java/android/text/DynamicLayout.java +++ b/core/java/android/text/DynamicLayout.java @@ -274,8 +274,11 @@ extends Layout sStaticLayout = null; } - if (reflowed == null) + if (reflowed == null) { reflowed = new StaticLayout(true); + } else { + reflowed.prepare(); + } reflowed.generate(text, where, where + after, getPaint(), getWidth(), getAlignment(), getTextDirectionHeuristic(), @@ -356,6 +359,7 @@ extends Layout synchronized (sLock) { sStaticLayout = reflowed; + reflowed.finish(); } } @@ -485,7 +489,7 @@ extends Layout private int mTopPadding, mBottomPadding; private static StaticLayout sStaticLayout = new StaticLayout(true); - private static Object sLock = new Object(); + private static final Object[] sLock = new Object[0]; private static final int START = 0; private static final int DIR = START; diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java index 2920ac5..c184c11 100644 --- a/core/java/android/text/MeasuredText.java +++ b/core/java/android/text/MeasuredText.java @@ -29,14 +29,15 @@ import com.android.internal.util.ArrayUtils; */ class MeasuredText { private static final boolean localLOGV = false; - /* package */ CharSequence mText; - /* package */ int mTextStart; - /* package */ float[] mWidths; - /* package */ char[] mChars; - /* package */ byte[] mLevels; - /* package */ int mDir; - /* package */ boolean mEasy; - /* package */ int mLen; + CharSequence mText; + int mTextStart; + float[] mWidths; + char[] mChars; + byte[] mLevels; + int mDir; + boolean mEasy; + int mLen; + private int mPos; private TextPaint mWorkPaint; @@ -44,16 +45,16 @@ class MeasuredText { mWorkPaint = new TextPaint(); } - private static MeasuredText[] cached = new MeasuredText[3]; + private static final Object[] sLock = new Object[0]; + private static MeasuredText[] sCached = new MeasuredText[3]; - /* package */ static MeasuredText obtain() { MeasuredText mt; - synchronized (cached) { - for (int i = cached.length; --i >= 0;) { - if (cached[i] != null) { - mt = cached[i]; - cached[i] = null; + synchronized (sLock) { + for (int i = sCached.length; --i >= 0;) { + if (sCached[i] != null) { + mt = sCached[i]; + sCached[i] = null; return mt; } } @@ -65,14 +66,14 @@ class MeasuredText { return mt; } - /* package */ static MeasuredText recycle(MeasuredText mt) { mt.mText = null; if (mt.mLen < 1000) { - synchronized(cached) { - for (int i = 0; i < cached.length; ++i) { - if (cached[i] == null) { - cached[i] = mt; + synchronized(sLock) { + for (int i = 0; i < sCached.length; ++i) { + if (sCached[i] == null) { + sCached[i] = mt; + mt.mText = null; break; } } @@ -84,7 +85,6 @@ class MeasuredText { /** * Analyzes text for bidirectional runs. Allocates working buffers. */ - /* package */ void setPara(CharSequence text, int start, int end, TextDirectionHeuristic textDir) { mText = text; mTextStart = start; diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index f7b9502..14c71b2 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -923,6 +923,14 @@ public class StaticLayout extends Layout { public void setMaximumVisibleLineCount(int lineCount) { mMaximumVisibleLineCount = lineCount; } + + void prepare() { + mMeasured = MeasuredText.obtain(); + } + + void finish() { + mMeasured = MeasuredText.recycle(mMeasured); + } private int mLineCount; private int mTopPadding, mBottomPadding; diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 346adc8..66d2641 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -135,7 +135,7 @@ public abstract class HardwareRenderer { /** * Updates the hardware renderer for the specified surface. * - * @param holder The holder for the surface to hardware accelerate. + * @param holder The holder for the surface to hardware accelerate */ abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException; @@ -148,9 +148,11 @@ public abstract class HardwareRenderer { /** * This method should be invoked whenever the current hardware renderer - * context should be reset. + * context should be reset. + * + * @param holder The holder for the surface to hardware accelerate */ - abstract void invalidate(); + abstract void invalidate(SurfaceHolder holder); /** * This method should be invoked to ensure the hardware renderer is in @@ -685,16 +687,17 @@ public abstract class HardwareRenderer { if (full && mCanvas != null) { mCanvas = null; } - - if (!isEnabled() || mDestroyed) return; - mDestroyed = true; + if (!isEnabled() || mDestroyed) { + setEnabled(false); + return; + } destroySurface(); + setEnabled(false); + mDestroyed = true; mGl = null; - - setEnabled(false); } void destroySurface() { @@ -706,13 +709,24 @@ public abstract class HardwareRenderer { } @Override - void invalidate() { + void invalidate(SurfaceHolder holder) { // Cancels any existing buffer to ensure we'll get a buffer // of the right size before we call eglSwapBuffers - sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, - EGL_NO_SURFACE, EGL_NO_CONTEXT); + sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + sEgl.eglDestroySurface(sEglDisplay, mEglSurface); + mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, holder, null); + + if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) { + int error = sEgl.eglGetError(); + if (error == EGL_BAD_NATIVE_WINDOW) { + Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); + return; + } + throw new RuntimeException("createWindowSurface failed " + + getEGLErrorString(error)); + } } - + @Override boolean validate() { return checkCurrent() != SURFACE_STATE_ERROR; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 914824c..935281a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -10291,6 +10291,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit canvas.restoreToCount(restoreCount); if (attachInfo != null) { + canvas.setBitmap(null); // Restore the cached Canvas for our siblings attachInfo.mCanvas = canvas; } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index b22ab7e..911bf2f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1344,7 +1344,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, mAttachInfo.mHardwareRenderer.isEnabled())) { mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight); if (!hwInitialized) { - mAttachInfo.mHardwareRenderer.invalidate(); + mAttachInfo.mHardwareRenderer.invalidate(mHolder); } } diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java index 9e9f46f..08ccd94 100644 --- a/core/java/android/view/VolumePanel.java +++ b/core/java/android/view/VolumePanel.java @@ -89,30 +89,16 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private static final int MSG_TIMEOUT = 5; private static final int MSG_RINGER_MODE_CHANGED = 6; -// private static final int RINGTONE_VOLUME_TEXT = com.android.internal.R.string.volume_ringtone; -// private static final int MUSIC_VOLUME_TEXT = com.android.internal.R.string.volume_music; -// private static final int INCALL_VOLUME_TEXT = com.android.internal.R.string.volume_call; -// private static final int ALARM_VOLUME_TEXT = com.android.internal.R.string.volume_alarm; -// private static final int UNKNOWN_VOLUME_TEXT = com.android.internal.R.string.volume_unknown; -// private static final int NOTIFICATION_VOLUME_TEXT = -// com.android.internal.R.string.volume_notification; -// private static final int BLUETOOTH_INCALL_VOLUME_TEXT = -// com.android.internal.R.string.volume_bluetooth_call; - protected Context mContext; private AudioManager mAudioManager; protected AudioService mAudioService; private boolean mRingIsSilent; + private boolean mShowCombinedVolumes; /** Dialog containing all the sliders */ private final Dialog mDialog; /** Dialog's content view */ private final View mView; -// private final TextView mMessage; -// private final TextView mAdditionalMessage; -// private final ImageView mSmallStreamIcon; -// private final ImageView mLargeStreamIcon; -// private final ProgressBar mLevel; /** Contains the sliders and their touchable icons */ private final ViewGroup mSliderGroup; @@ -127,7 +113,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private HashMap<Integer,StreamControl> mStreamControls; // List of stream types and their order - // RING and VOICE_CALL are hidden unless explicitly requested + // RING, VOICE_CALL & BLUETOOTH_SCO are hidden unless explicitly requested private static final int [] STREAM_TYPES = { AudioManager.STREAM_BLUETOOTH_SCO, AudioManager.STREAM_RING, @@ -136,10 +122,18 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie AudioManager.STREAM_NOTIFICATION }; + private static final int [] CONTENT_DESCRIPTIONS = { + R.string.volume_icon_description_bluetooth, + R.string.volume_icon_description_ringer, + R.string.volume_icon_description_incall, + R.string.volume_icon_description_media, + R.string.volume_icon_description_notification + }; + // These icons need to correspond to the ones above. private static final int [] STREAM_ICONS_NORMAL = { R.drawable.ic_audio_bt, - R.drawable.ic_audio_phone, + R.drawable.ic_audio_ring_notif, R.drawable.ic_audio_phone, R.drawable.ic_audio_vol, R.drawable.ic_audio_notification, @@ -148,7 +142,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie // These icons need to correspond to the ones above. private static final int [] STREAM_ICONS_MUTED = { R.drawable.ic_audio_bt, - R.drawable.ic_audio_phone, + R.drawable.ic_audio_ring_notif_mute, R.drawable.ic_audio_phone, R.drawable.ic_audio_vol_mute, R.drawable.ic_audio_notification_mute, @@ -184,7 +178,6 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie }); mSliderGroup = (ViewGroup) mView.findViewById(R.id.slider_group); mMoreButton = (ImageView) mView.findViewById(R.id.expand_button); - mMoreButton.setOnClickListener(this); mDivider = (ImageView) mView.findViewById(R.id.expand_button_divider); mDialog = new Dialog(context, R.style.Theme_Panel_Volume); @@ -205,16 +198,18 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie window.setAttributes(lp); window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); -// mMessage = (TextView) view.findViewById(com.android.internal.R.id.message); -// mAdditionalMessage = -// (TextView) view.findViewById(com.android.internal.R.id.additional_message); -// mSmallStreamIcon = (ImageView) view.findViewById(com.android.internal.R.id.other_stream_icon); -// mLargeStreamIcon = (ImageView) view.findViewById(com.android.internal.R.id.ringer_stream_icon); -// mLevel = (ProgressBar) view.findViewById(com.android.internal.R.id.level); - mToneGenerators = new ToneGenerator[AudioSystem.getNumStreamTypes()]; mVibrator = new Vibrator(); + mShowCombinedVolumes = !context.getResources().getBoolean(R.bool.config_voice_capable); + // If we don't want to show multiple volumes, hide the settings button and divider + if (!mShowCombinedVolumes) { + mMoreButton.setVisibility(View.GONE); + mDivider.setVisibility(View.GONE); + } else { + mMoreButton.setOnClickListener(this); + } + listenToRingerMode(); } @@ -242,6 +237,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie LayoutInflater inflater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); mStreamControls = new HashMap<Integer,StreamControl>(STREAM_TYPES.length); + Resources res = mContext.getResources(); for (int i = 0; i < STREAM_TYPES.length; i++) { StreamControl sc = new StreamControl(); sc.streamType = STREAM_TYPES[i]; @@ -250,6 +246,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie sc.icon = (ImageView) sc.group.findViewById(R.id.stream_icon); sc.icon.setOnClickListener(this); sc.icon.setTag(sc); + sc.icon.setContentDescription(res.getString(CONTENT_DESCRIPTIONS[i])); sc.iconRes = STREAM_ICONS_NORMAL[i]; sc.iconMuteRes = STREAM_ICONS_MUTED[i]; sc.icon.setImageResource(sc.iconRes); @@ -275,13 +272,19 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie updateSlider(active); } + addOtherVolumes(); + } + + private void addOtherVolumes() { + if (!mShowCombinedVolumes) return; + for (int i = 0; i < STREAM_TYPES.length; i++) { // Skip the phone specific ones and the active one final int streamType = STREAM_TYPES[i]; if (streamType == AudioManager.STREAM_RING || streamType == AudioManager.STREAM_VOICE_CALL || streamType == AudioManager.STREAM_BLUETOOTH_SCO - || streamType == activeStreamType) { + || streamType == mActiveStreamType) { continue; } StreamControl sc = mStreamControls.get(streamType); @@ -392,31 +395,23 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie case AudioManager.STREAM_RING: { // setRingerIcon(); -// message = RINGTONE_VOLUME_TEXT; Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri( mContext, RingtoneManager.TYPE_RINGTONE); if (ringuri == null) { -// additionalMessage = -// com.android.internal.R.string.volume_music_hint_silent_ringtone_selected; mRingIsSilent = true; } break; } case AudioManager.STREAM_MUSIC: { -// message = MUSIC_VOLUME_TEXT; // Special case for when Bluetooth is active for music if ((mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC) & (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) { -// additionalMessage = -// com.android.internal.R.string.volume_music_hint_playing_through_bluetooth; -// setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_ad2p); setMusicIcon(R.drawable.ic_audio_bt, R.drawable.ic_audio_bt_mute); } else { setMusicIcon(R.drawable.ic_audio_vol, R.drawable.ic_audio_vol_mute); -// setSmallIcon(index); } break; } @@ -429,25 +424,17 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie */ index++; max++; -// message = INCALL_VOLUME_TEXT; -// setSmallIcon(index); break; } case AudioManager.STREAM_ALARM: { -// message = ALARM_VOLUME_TEXT; -// setSmallIcon(index); break; } case AudioManager.STREAM_NOTIFICATION: { -// message = NOTIFICATION_VOLUME_TEXT; -// setSmallIcon(index); Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri( mContext, RingtoneManager.TYPE_NOTIFICATION); if (ringuri == null) { -// additionalMessage = -// com.android.internal.R.string.volume_music_hint_silent_ringtone_selected; mRingIsSilent = true; } break; @@ -461,29 +448,10 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie */ index++; max++; -// message = BLUETOOTH_INCALL_VOLUME_TEXT; -// setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_in_call); break; } } -// String messageString = Resources.getSystem().getString(message); -// if (!mMessage.getText().equals(messageString)) { -// mMessage.setText(messageString); -// } -// -// if (additionalMessage == 0) { -// mAdditionalMessage.setVisibility(View.GONE); -// } else { -// mAdditionalMessage.setVisibility(View.VISIBLE); -// mAdditionalMessage.setText(Resources.getSystem().getString(additionalMessage)); -// } - -// if (max != mLevel.getMax()) { -// mLevel.setMax(max); -// } -// mLevel.setProgress(index); - StreamControl sc = mStreamControls.get(streamType); if (sc != null) { sc.seekbarView.setProgress(index); @@ -493,7 +461,9 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie mAudioManager.forceVolumeControlStream(streamType); mDialog.setContentView(mView); // Showing dialog - use collapsed state - collapse(); + if (mShowCombinedVolumes) { + collapse(); + } mDialog.show(); } @@ -566,31 +536,6 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie } // /** -// * Makes the small icon visible, and hides the large icon. -// * -// * @param index The volume index, where 0 means muted. -// */ -// private void setSmallIcon(int index) { -// mLargeStreamIcon.setVisibility(View.GONE); -// mSmallStreamIcon.setVisibility(View.VISIBLE); -// -// mSmallStreamIcon.setImageResource(index == 0 -// ? com.android.internal.R.drawable.ic_volume_off_small -// : com.android.internal.R.drawable.ic_volume_small); -// } -// -// /** -// * Makes the large image view visible with the given icon. -// * -// * @param resId The icon to display. -// */ -// private void setLargeIcon(int resId) { -// mSmallStreamIcon.setVisibility(View.GONE); -// mLargeStreamIcon.setVisibility(View.VISIBLE); -// mLargeStreamIcon.setImageResource(resId); -// } -// -// /** // * Makes the ringer icon visible with an icon that is chosen // * based on the current ringer mode. // */ @@ -627,11 +572,6 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie } protected void onFreeResources() { - // We'll keep the views, just ditch the cached drawable and hence - // bitmaps -// mSmallStreamIcon.setImageDrawable(null); -// mLargeStreamIcon.setImageDrawable(null); - synchronized (this) { for (int i = mToneGenerators.length - 1; i >= 0; i--) { if (mToneGenerators[i] != null) { @@ -718,7 +658,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie mAudioManager.setRingerMode(mAudioManager.isSilentMode() ? AudioManager.RINGER_MODE_NORMAL : AudioManager.RINGER_MODE_SILENT); // Expand the dialog if it hasn't been expanded yet. - if (!isExpanded()) expand(); + if (mShowCombinedVolumes && !isExpanded()) expand(); } resetTimeout(); } diff --git a/core/java/android/service/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java index 0dff3a6..bf07e71 100644 --- a/core/java/android/service/textservice/SpellCheckerSession.java +++ b/core/java/android/view/textservice/SpellCheckerSession.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.service.textservice; +package android.view.textservice; import com.android.internal.textservice.ISpellCheckerSession; import com.android.internal.textservice.ISpellCheckerSessionListener; @@ -38,6 +38,12 @@ import java.util.Queue; public class SpellCheckerSession { private static final String TAG = SpellCheckerSession.class.getSimpleName(); private static final boolean DBG = false; + /** + * Name under which a SpellChecker service component publishes information about itself. + * This meta-data must reference an XML resource. + **/ + public static final String SERVICE_META_DATA = "android.view.textservice.scs"; + private static final int MSG_ON_GET_SUGGESTION_MULTIPLE = 1; diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java index ae253cf..a60eb24 100644 --- a/core/java/android/view/textservice/TextServicesManager.java +++ b/core/java/android/view/textservice/TextServicesManager.java @@ -22,9 +22,9 @@ import android.content.Context; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; -import android.service.textservice.SpellCheckerSession; -import android.service.textservice.SpellCheckerSession.SpellCheckerSessionListener; import android.util.Log; +import android.view.textservice.SpellCheckerSession; +import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener; import java.util.Locale; @@ -81,18 +81,18 @@ public final class TextServicesManager { } // TODO: set a proper locale instead of the dummy locale final String localeString = locale == null ? "en" : locale.toString(); - final SpellCheckerInfo info; + final SpellCheckerInfo sci; try { - info = sService.getCurrentSpellChecker(localeString); + sci = sService.getCurrentSpellChecker(localeString); } catch (RemoteException e) { return null; } - if (info == null) { + if (sci == null) { return null; } - final SpellCheckerSession session = new SpellCheckerSession(info, sService, listener); + final SpellCheckerSession session = new SpellCheckerSession(sci, sService, listener); try { - sService.getSpellCheckerService(info, localeString, + sService.getSpellCheckerService(sci.getId(), localeString, session.getTextServicesSessionListener(), session.getSpellCheckerSessionListener()); } catch (RemoteException e) { @@ -128,4 +128,18 @@ public final class TextServicesManager { return null; } } + + /** + * @hide + */ + public void setCurrentSpellChecker(SpellCheckerInfo sci) { + try { + if (sci == null) { + throw new NullPointerException("SpellCheckerInfo is null"); + } + sService.setCurrentSpellChecker(sci.getId()); + } catch (RemoteException e) { + Log.e(TAG, "Error in setCurrentSpellChecker: " + e); + } + } } diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 1f29b16..946f009 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -2428,7 +2428,7 @@ public class ListView extends AbsListView { if (mItemsCanFocus && (focusResult == null) && selectedView != null && selectedView.hasFocus()) { final View focused = selectedView.findFocus(); - if (distanceToView(focused) > 0) { + if (!isViewAncestorOf(focused, this) || distanceToView(focused) > 0) { focused.clearFocus(); } } |
