diff --git a/api/current.xml b/api/current.xml index 4db6e661b94df..860cce4b9df52 100644 --- a/api/current.xml +++ b/api/current.xml @@ -309,6 +309,17 @@ visibility="public" > + + - + + + + + + + + + + + + + + + + + + + + + + - - + + - + + - - - - - - - @@ -50410,6 +50472,259 @@ > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mContext; + private final int mResourceId; + + public ResourceGestureLibrary(Context context, int resourceId) { + mContext = new WeakReference(context); + mResourceId = resourceId; + } + + @Override + public boolean isReadOnly() { + return true; + } + + public boolean save() { + return false; + } + + public boolean load() { + boolean result = false; + final Context context = mContext.get(); + if (context != null) { + final InputStream in = context.getResources().openRawResource(mResourceId); + try { + mStore.load(in, true); + result = true; + } catch (IOException e) { + Log.d(LOG_TAG, "Could not load the gesture library from raw resource " + + context.getResources().getResourceName(mResourceId), e); + } + } + + return result; + } + } +} diff --git a/core/java/android/gesture/GestureLibrary.java b/core/java/android/gesture/GestureLibrary.java index 1cf192ec34461..a29c2c83cfbf0 100644 --- a/core/java/android/gesture/GestureLibrary.java +++ b/core/java/android/gesture/GestureLibrary.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 The Android Open Source Project + * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,333 +14,68 @@ * limitations under the License. */ + package android.gesture; -import android.util.Log; -import android.os.SystemClock; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.DataOutputStream; -import java.io.DataInputStream; -import java.util.ArrayList; -import java.util.HashMap; import java.util.Set; -import java.util.Map; +import java.util.ArrayList; -import static android.gesture.GestureConstants.LOG_TAG; +public abstract class GestureLibrary { + protected final GestureStore mStore; -/** - * GestureLibrary maintains gesture examples and makes predictions on a new - * gesture - */ -// -// File format for GestureLibrary: -// -// Nb. bytes Java type Description -// ----------------------------------- -// Header -// 2 bytes short File format version number -// 4 bytes int Number of entries -// Entry -// X bytes UTF String Entry name -// 4 bytes int Number of gestures -// Gesture -// 8 bytes long Gesture ID -// 4 bytes int Number of strokes -// Stroke -// 4 bytes int Number of points -// Point -// 4 bytes float X coordinate of the point -// 4 bytes float Y coordinate of the point -// 8 bytes long Time stamp -// -public class GestureLibrary { - public static final int SEQUENCE_INVARIANT = 1; - // when SEQUENCE_SENSITIVE is used, only single stroke gestures are currently allowed - public static final int SEQUENCE_SENSITIVE = 2; - - // ORIENTATION_SENSITIVE and ORIENTATION_INVARIANT are only for SEQUENCE_SENSITIVE gestures - public static final int ORIENTATION_INVARIANT = 1; - public static final int ORIENTATION_SENSITIVE = 2; - - private static final short FILE_FORMAT_VERSION = 1; - - private static final boolean PROFILE_LOADING_SAVING = false; - - private int mSequenceType = SEQUENCE_SENSITIVE; - private int mOrientationStyle = ORIENTATION_SENSITIVE; - - private final String mGestureFileName; - - private final HashMap> mNamedGestures = - new HashMap>(); - - private Learner mClassifier; - - private boolean mChanged = false; - - /** - * @param path where gesture data is stored - */ - public GestureLibrary(String path) { - mGestureFileName = path; - mClassifier = new InstanceLearner(); + protected GestureLibrary() { + mStore = new GestureStore(); + } + + public abstract boolean save(); + + public abstract boolean load(); + + public boolean isReadOnly() { + return false; + } + + public Learner getLearner() { + return mStore.getLearner(); } - /** - * Specify how the gesture library will handle orientation. - * Use ORIENTATION_INVARIANT or ORIENTATION_SENSITIVE - * - * @param style - */ public void setOrientationStyle(int style) { - mOrientationStyle = style; + mStore.setOrientationStyle(style); } public int getOrientationStyle() { - return mOrientationStyle; + return mStore.getOrientationStyle(); } - /** - * @param type SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE - */ public void setSequenceType(int type) { - mSequenceType = type; + mStore.setSequenceType(type); } - /** - * @return SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE - */ public int getSequenceType() { - return mSequenceType; + return mStore.getSequenceType(); } - /** - * Get all the gesture entry names in the library - * - * @return a set of strings - */ public Set getGestureEntries() { - return mNamedGestures.keySet(); + return mStore.getGestureEntries(); } - /** - * Recognize a gesture - * - * @param gesture the query - * @return a list of predictions of possible entries for a given gesture - */ public ArrayList recognize(Gesture gesture) { - Instance instance = Instance.createInstance(mSequenceType, gesture, null); - return mClassifier.classify(mSequenceType, instance.vector); + return mStore.recognize(gesture); } - /** - * Add a gesture for the entry - * - * @param entryName entry name - * @param gesture - */ public void addGesture(String entryName, Gesture gesture) { - if (entryName == null || entryName.length() == 0) { - return; - } - ArrayList gestures = mNamedGestures.get(entryName); - if (gestures == null) { - gestures = new ArrayList(); - mNamedGestures.put(entryName, gestures); - } - gestures.add(gesture); - mClassifier.addInstance(Instance.createInstance(mSequenceType, gesture, entryName)); - mChanged = true; + mStore.addGesture(entryName, gesture); } - /** - * Remove a gesture from the library. If there are no more gestures for the - * given entry, the gesture entry will be removed. - * - * @param entryName entry name - * @param gesture - */ public void removeGesture(String entryName, Gesture gesture) { - ArrayList gestures = mNamedGestures.get(entryName); - if (gestures == null) { - return; - } - - gestures.remove(gesture); - - // if there are no more samples, remove the entry automatically - if (gestures.isEmpty()) { - mNamedGestures.remove(entryName); - } - - mClassifier.removeInstance(gesture.getID()); - - mChanged = true; + mStore.removeGesture(entryName, gesture); } - /** - * Remove a entry of gestures - * - * @param entryName the entry name - */ public void removeEntry(String entryName) { - mNamedGestures.remove(entryName); - mClassifier.removeInstances(entryName); - mChanged = true; + mStore.removeEntry(entryName); } - /** - * Get all the gestures of an entry - * - * @param entryName - * @return the list of gestures that is under this name - */ public ArrayList getGestures(String entryName) { - ArrayList gestures = mNamedGestures.get(entryName); - if (gestures != null) { - return new ArrayList(gestures); - } else { - return null; - } - } - - /** - * Save the gesture library - */ - public boolean save() { - if (!mChanged) { - return true; - } - - boolean result = false; - DataOutputStream out = null; - - try { - File file = new File(mGestureFileName); - if (!file.getParentFile().exists()) { - if (!file.getParentFile().mkdirs()) { - return false; - } - } - - long start; - if (PROFILE_LOADING_SAVING) { - start = SystemClock.elapsedRealtime(); - } - - final HashMap> maps = mNamedGestures; - - out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file), - GestureConstants.IO_BUFFER_SIZE)); - // Write version number - out.writeShort(FILE_FORMAT_VERSION); - // Write number of entries - out.writeInt(maps.size()); - - for (Map.Entry> entry : maps.entrySet()) { - final String key = entry.getKey(); - final ArrayList examples = entry.getValue(); - final int count = examples.size(); - - // Write entry name - out.writeUTF(key); - // Write number of examples for this entry - out.writeInt(count); - - for (int i = 0; i < count; i++) { - examples.get(i).serialize(out); - } - } - - out.flush(); - - if (PROFILE_LOADING_SAVING) { - long end = SystemClock.elapsedRealtime(); - Log.d(LOG_TAG, "Saving gestures library = " + (end - start) + " ms"); - } - - mChanged = false; - result = true; - } catch (IOException ex) { - Log.d(LOG_TAG, "Failed to save gestures:", ex); - } finally { - GestureUtilities.closeStream(out); - } - - return result; - } - - /** - * Load the gesture library - */ - public boolean load() { - boolean result = false; - - final File file = new File(mGestureFileName); - if (file.exists()) { - DataInputStream in = null; - try { - in = new DataInputStream(new BufferedInputStream( - new FileInputStream(mGestureFileName), GestureConstants.IO_BUFFER_SIZE)); - - long start; - if (PROFILE_LOADING_SAVING) { - start = SystemClock.elapsedRealtime(); - } - - // Read file format version number - final short versionNumber = in.readShort(); - switch (versionNumber) { - case 1: - readFormatV1(in); - break; - } - - if (PROFILE_LOADING_SAVING) { - long end = SystemClock.elapsedRealtime(); - Log.d(LOG_TAG, "Loading gestures library = " + (end - start) + " ms"); - } - - result = true; - } catch (IOException ex) { - Log.d(LOG_TAG, "Failed to load gestures:", ex); - } finally { - GestureUtilities.closeStream(in); - } - } - - return result; - } - - private void readFormatV1(DataInputStream in) throws IOException { - final Learner classifier = mClassifier; - final HashMap> namedGestures = mNamedGestures; - namedGestures.clear(); - - // Number of entries in the library - final int entriesCount = in.readInt(); - - for (int i = 0; i < entriesCount; i++) { - // Entry name - final String name = in.readUTF(); - // Number of gestures - final int gestureCount = in.readInt(); - - final ArrayList gestures = new ArrayList(gestureCount); - for (int j = 0; j < gestureCount; j++) { - final Gesture gesture = Gesture.deserialize(in); - gestures.add(gesture); - classifier.addInstance(Instance.createInstance(mSequenceType, gesture, name)); - } - - namedGestures.put(name, gestures); - } + return mStore.getGestures(entryName); } } diff --git a/core/java/android/gesture/GestureOverlayView.java b/core/java/android/gesture/GestureOverlayView.java index c21cc55c7c8b3..227cf3d9a2745 100755 --- a/core/java/android/gesture/GestureOverlayView.java +++ b/core/java/android/gesture/GestureOverlayView.java @@ -45,8 +45,9 @@ import java.util.ArrayList; * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeAngleThreshold * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeLengthThreshold * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeSquarenessThreshold - * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeType + * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeType * @attr ref android.R.styleable#GestureOverlayView_gestureColor + * @attr ref android.R.styleable#GestureOverlayView_orientation * @attr ref android.R.styleable#GestureOverlayView_uncertainGestureColor */ public class GestureOverlayView extends FrameLayout { @@ -75,7 +76,7 @@ public class GestureOverlayView extends FrameLayout { private int mInvalidateExtraBorder = 10; private int mGestureStrokeType = GESTURE_STROKE_TYPE_SINGLE; - private float mGestureStrokeLengthThreshold = 30.0f; + private float mGestureStrokeLengthThreshold = 50.0f; private float mGestureStrokeSquarenessTreshold = 0.275f; private float mGestureStrokeAngleThreshold = 40.0f; @@ -86,7 +87,7 @@ public class GestureOverlayView extends FrameLayout { private float mX; private float mY; - + private float mCurveEndX; private float mCurveEndY; @@ -516,12 +517,12 @@ public class GestureOverlayView extends FrameLayout { final int count = listeners.size(); for (int i = 0; i < count; i++) { listeners.get(i).onGestureStarted(this, event); - } + } } private Rect touchMove(MotionEvent event) { Rect areaToRefresh = null; - + final float x = event.getX(); final float y = event.getY(); @@ -530,7 +531,7 @@ public class GestureOverlayView extends FrameLayout { final float dx = Math.abs(x - previousX); final float dy = Math.abs(y - previousY); - + if (dx >= GestureStroke.TOUCH_TOLERANCE || dy >= GestureStroke.TOUCH_TOLERANCE) { areaToRefresh = mInvalidRect; @@ -538,55 +539,55 @@ public class GestureOverlayView extends FrameLayout { final int border = mInvalidateExtraBorder; areaToRefresh.set((int) mCurveEndX - border, (int) mCurveEndY - border, (int) mCurveEndX + border, (int) mCurveEndY + border); - + float cX = mCurveEndX = (x + previousX) / 2; float cY = mCurveEndY = (y + previousY) / 2; mPath.quadTo(previousX, previousY, cX, cY); - + // union with the control point of the new curve areaToRefresh.union((int) previousX - border, (int) previousY - border, (int) previousX + border, (int) previousY + border); - + // union with the end point of the new curve areaToRefresh.union((int) cX - border, (int) cY - border, (int) cX + border, (int) cY + border); mX = x; mY = y; - } - mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime())); + mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime())); - if (mHandleGestureActions && !mIsGesturing) { - mTotalLength += (float) Math.sqrt(dx * dx + dy * dy); + if (mHandleGestureActions && !mIsGesturing) { + mTotalLength += (float) Math.sqrt(dx * dx + dy * dy); - if (mTotalLength > mGestureStrokeLengthThreshold) { - final OrientedBoundingBox box = - GestureUtilities.computeOrientedBoundingBox(mStrokeBuffer); + if (mTotalLength > mGestureStrokeLengthThreshold) { + final OrientedBoundingBox box = + GestureUtilities.computeOrientedBoundingBox(mStrokeBuffer); - float angle = Math.abs(box.orientation); - if (angle > 90) { - angle = 180 - angle; - } + float angle = Math.abs(box.orientation); + if (angle > 90) { + angle = 180 - angle; + } - if (box.squareness > mGestureStrokeSquarenessTreshold || - (mOrientation == ORIENTATION_VERTICAL ? - angle < mGestureStrokeAngleThreshold : - angle > mGestureStrokeAngleThreshold)) { + if (box.squareness > mGestureStrokeSquarenessTreshold || + (mOrientation == ORIENTATION_VERTICAL ? + angle < mGestureStrokeAngleThreshold : + angle > mGestureStrokeAngleThreshold)) { - mIsGesturing = true; - setCurrentColor(mCertainGestureColor); + mIsGesturing = true; + setCurrentColor(mCertainGestureColor); + } } } - } - // pass the event to handlers - final ArrayList listeners = mOnGestureListeners; - final int count = listeners.size(); - for (int i = 0; i < count; i++) { - listeners.get(i).onGesture(this, event); - } + // pass the event to handlers + final ArrayList listeners = mOnGestureListeners; + final int count = listeners.size(); + for (int i = 0; i < count; i++) { + listeners.get(i).onGesture(this, event); + } + } return areaToRefresh; } @@ -594,35 +595,45 @@ public class GestureOverlayView extends FrameLayout { private void touchUp(MotionEvent event, boolean cancel) { mIsListeningForGestures = false; - // add the stroke to the current gesture - mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer)); - mStrokeBuffer.clear(); + // A gesture wasn't started or was cancelled + if (mCurrentGesture != null) { + // add the stroke to the current gesture + mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer)); - if (!cancel) { - // pass the event to handlers - final ArrayList listeners = mOnGestureListeners; - int count = listeners.size(); - for (int i = 0; i < count; i++) { - listeners.get(i).onGestureEnded(this, event); - } + if (!cancel) { + // pass the event to handlers + final ArrayList listeners = mOnGestureListeners; + int count = listeners.size(); + for (int i = 0; i < count; i++) { + listeners.get(i).onGestureEnded(this, event); + } + + if (mHandleGestureActions) { + clear(mFadeEnabled, mIsGesturing); + } + } else { + cancelGesture(event); - if (mHandleGestureActions) { - clear(mFadeEnabled, mIsGesturing); } } else { - // pass the event to handlers - final ArrayList listeners = mOnGestureListeners; - final int count = listeners.size(); - for (int i = 0; i < count; i++) { - listeners.get(i).onGestureCancelled(this, event); - } - - clear(false); + cancelGesture(event); } + mStrokeBuffer.clear(); mIsGesturing = false; } + private void cancelGesture(MotionEvent event) { + // pass the event to handlers + final ArrayList listeners = mOnGestureListeners; + final int count = listeners.size(); + for (int i = 0; i < count; i++) { + listeners.get(i).onGestureCancelled(this, event); + } + + clear(false); + } + private void fireOnGesturePerformed() { final ArrayList actionListeners = mOnGesturePerformedListeners; @@ -668,7 +679,7 @@ public class GestureOverlayView extends FrameLayout { setPaintAlpha(255); } - invalidate(); + invalidate(); } } diff --git a/core/java/android/gesture/GestureStore.java b/core/java/android/gesture/GestureStore.java new file mode 100644 index 0000000000000..ddf1c8330b171 --- /dev/null +++ b/core/java/android/gesture/GestureStore.java @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2008-2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +import android.util.Log; +import android.os.SystemClock; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.DataOutputStream; +import java.io.DataInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Set; +import java.util.Map; + +import static android.gesture.GestureConstants.LOG_TAG; + +/** + * GestureLibrary maintains gesture examples and makes predictions on a new + * gesture + */ +// +// File format for GestureStore: +// +// Nb. bytes Java type Description +// ----------------------------------- +// Header +// 2 bytes short File format version number +// 4 bytes int Number of entries +// Entry +// X bytes UTF String Entry name +// 4 bytes int Number of gestures +// Gesture +// 8 bytes long Gesture ID +// 4 bytes int Number of strokes +// Stroke +// 4 bytes int Number of points +// Point +// 4 bytes float X coordinate of the point +// 4 bytes float Y coordinate of the point +// 8 bytes long Time stamp +// +public class GestureStore { + public static final int SEQUENCE_INVARIANT = 1; + // when SEQUENCE_SENSITIVE is used, only single stroke gestures are currently allowed + public static final int SEQUENCE_SENSITIVE = 2; + + // ORIENTATION_SENSITIVE and ORIENTATION_INVARIANT are only for SEQUENCE_SENSITIVE gestures + public static final int ORIENTATION_INVARIANT = 1; + public static final int ORIENTATION_SENSITIVE = 2; + + private static final short FILE_FORMAT_VERSION = 1; + + private static final boolean PROFILE_LOADING_SAVING = false; + + private int mSequenceType = SEQUENCE_SENSITIVE; + private int mOrientationStyle = ORIENTATION_SENSITIVE; + + private final HashMap> mNamedGestures = + new HashMap>(); + + private Learner mClassifier; + + private boolean mChanged = false; + + public GestureStore() { + mClassifier = new InstanceLearner(); + } + + /** + * Specify how the gesture library will handle orientation. + * Use ORIENTATION_INVARIANT or ORIENTATION_SENSITIVE + * + * @param style + */ + public void setOrientationStyle(int style) { + mOrientationStyle = style; + } + + public int getOrientationStyle() { + return mOrientationStyle; + } + + /** + * @param type SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE + */ + public void setSequenceType(int type) { + mSequenceType = type; + } + + /** + * @return SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE + */ + public int getSequenceType() { + return mSequenceType; + } + + /** + * Get all the gesture entry names in the library + * + * @return a set of strings + */ + public Set getGestureEntries() { + return mNamedGestures.keySet(); + } + + /** + * Recognize a gesture + * + * @param gesture the query + * @return a list of predictions of possible entries for a given gesture + */ + public ArrayList recognize(Gesture gesture) { + Instance instance = Instance.createInstance(mSequenceType, + mOrientationStyle, gesture, null); + return mClassifier.classify(mSequenceType, instance.vector); + } + + /** + * Add a gesture for the entry + * + * @param entryName entry name + * @param gesture + */ + public void addGesture(String entryName, Gesture gesture) { + if (entryName == null || entryName.length() == 0) { + return; + } + ArrayList gestures = mNamedGestures.get(entryName); + if (gestures == null) { + gestures = new ArrayList(); + mNamedGestures.put(entryName, gestures); + } + gestures.add(gesture); + mClassifier.addInstance( + Instance.createInstance(mSequenceType, mOrientationStyle, gesture, entryName)); + mChanged = true; + } + + /** + * Remove a gesture from the library. If there are no more gestures for the + * given entry, the gesture entry will be removed. + * + * @param entryName entry name + * @param gesture + */ + public void removeGesture(String entryName, Gesture gesture) { + ArrayList gestures = mNamedGestures.get(entryName); + if (gestures == null) { + return; + } + + gestures.remove(gesture); + + // if there are no more samples, remove the entry automatically + if (gestures.isEmpty()) { + mNamedGestures.remove(entryName); + } + + mClassifier.removeInstance(gesture.getID()); + + mChanged = true; + } + + /** + * Remove a entry of gestures + * + * @param entryName the entry name + */ + public void removeEntry(String entryName) { + mNamedGestures.remove(entryName); + mClassifier.removeInstances(entryName); + mChanged = true; + } + + /** + * Get all the gestures of an entry + * + * @param entryName + * @return the list of gestures that is under this name + */ + public ArrayList getGestures(String entryName) { + ArrayList gestures = mNamedGestures.get(entryName); + if (gestures != null) { + return new ArrayList(gestures); + } else { + return null; + } + } + + /** + * Save the gesture library + */ + public void save(OutputStream stream) throws IOException { + save(stream, false); + } + + public void save(OutputStream stream, boolean closeStream) throws IOException { + if (!mChanged) { + return; + } + + DataOutputStream out = null; + + try { + long start; + if (PROFILE_LOADING_SAVING) { + start = SystemClock.elapsedRealtime(); + } + + final HashMap> maps = mNamedGestures; + + out = new DataOutputStream((stream instanceof BufferedOutputStream) ? out : + new BufferedOutputStream(out, GestureConstants.IO_BUFFER_SIZE)); + // Write version number + out.writeShort(FILE_FORMAT_VERSION); + // Write number of entries + out.writeInt(maps.size()); + + for (Map.Entry> entry : maps.entrySet()) { + final String key = entry.getKey(); + final ArrayList examples = entry.getValue(); + final int count = examples.size(); + + // Write entry name + out.writeUTF(key); + // Write number of examples for this entry + out.writeInt(count); + + for (int i = 0; i < count; i++) { + examples.get(i).serialize(out); + } + } + + out.flush(); + + if (PROFILE_LOADING_SAVING) { + long end = SystemClock.elapsedRealtime(); + Log.d(LOG_TAG, "Saving gestures library = " + (end - start) + " ms"); + } + + mChanged = false; + } finally { + if (closeStream) GestureUtilities.closeStream(out); + } + } + + /** + * Load the gesture library + */ + public void load(InputStream stream) throws IOException { + load(stream, false); + } + + public void load(InputStream stream, boolean closeStream) throws IOException { + DataInputStream in = null; + try { + in = new DataInputStream((stream instanceof BufferedInputStream) ? stream : + new BufferedInputStream(stream, GestureConstants.IO_BUFFER_SIZE)); + + long start; + if (PROFILE_LOADING_SAVING) { + start = SystemClock.elapsedRealtime(); + } + + // Read file format version number + final short versionNumber = in.readShort(); + switch (versionNumber) { + case 1: + readFormatV1(in); + break; + } + + if (PROFILE_LOADING_SAVING) { + long end = SystemClock.elapsedRealtime(); + Log.d(LOG_TAG, "Loading gestures library = " + (end - start) + " ms"); + } + } finally { + if (closeStream) GestureUtilities.closeStream(in); + } + } + + private void readFormatV1(DataInputStream in) throws IOException { + final Learner classifier = mClassifier; + final HashMap> namedGestures = mNamedGestures; + namedGestures.clear(); + + // Number of entries in the library + final int entriesCount = in.readInt(); + + for (int i = 0; i < entriesCount; i++) { + // Entry name + final String name = in.readUTF(); + // Number of gestures + final int gestureCount = in.readInt(); + + final ArrayList gestures = new ArrayList(gestureCount); + for (int j = 0; j < gestureCount; j++) { + final Gesture gesture = Gesture.deserialize(in); + gestures.add(gesture); + classifier.addInstance( + Instance.createInstance(mSequenceType, mOrientationStyle, gesture, name)); + } + + namedGestures.put(name, gestures); + } + } + + Learner getLearner() { + return mClassifier; + } +} diff --git a/core/java/android/gesture/GestureStroke.java b/core/java/android/gesture/GestureStroke.java index 0d7bc2d049d4e..598eb8534ffc5 100644 --- a/core/java/android/gesture/GestureStroke.java +++ b/core/java/android/gesture/GestureStroke.java @@ -17,7 +17,6 @@ package android.gesture; import android.graphics.Canvas; -import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; @@ -31,7 +30,7 @@ import java.util.ArrayList; * A gesture stroke started on a touch down and ended on a touch up. */ public class GestureStroke { - static final float TOUCH_TOLERANCE = 3; + static final float TOUCH_TOLERANCE = 8; public final RectF boundingBox; @@ -147,10 +146,12 @@ public class GestureStroke { final float[] pts = GestureUtilities.temporalSampling(this, numSample); final RectF rect = boundingBox; - final Matrix matrix = new Matrix(); - matrix.setTranslate(-rect.left, -rect.top); - matrix.postScale(width / rect.width(), height / rect.height()); - matrix.mapPoints(pts); + GestureUtilities.translate(pts, -rect.left, -rect.top); + + float sx = width / rect.width(); + float sy = height / rect.height(); + float scale = sx > sy ? sy : sx; + GestureUtilities.scale(pts, scale, scale); float mX = 0; float mY = 0; diff --git a/core/java/android/gesture/GestureUtilities.java b/core/java/android/gesture/GestureUtilities.java index 4a3144c2f0b74..40d70295fc9b2 100755 --- a/core/java/android/gesture/GestureUtilities.java +++ b/core/java/android/gesture/GestureUtilities.java @@ -17,7 +17,6 @@ package android.gesture; import android.graphics.RectF; -import android.graphics.Matrix; import android.util.Log; import java.util.ArrayList; @@ -380,22 +379,17 @@ final class GestureUtilities { } static OrientedBoundingBox computeOrientedBoundingBox(float[] points, float[] centroid) { - Matrix tr = new Matrix(); - tr.setTranslate(-centroid[0], -centroid[1]); - tr.mapPoints(points); + translate(points, -centroid[0], -centroid[1]); double[][] array = computeCoVariance(points); double[] targetVector = computeOrientation(array); float angle; if (targetVector[0] == 0 && targetVector[1] == 0) { - angle = -90; + angle = (float) -Math.PI/2; } else { // -PI classify(int gestureType, float[] vector) { + ArrayList classify(int sequenceType, float[] vector) { ArrayList predictions = new ArrayList(); ArrayList instances = getInstances(); int count = instances.size(); @@ -43,7 +38,7 @@ class InstanceLearner extends Learner { continue; } double distance; - if (gestureType == GestureLibrary.SEQUENCE_SENSITIVE) { + if (sequenceType == GestureStore.SEQUENCE_SENSITIVE) { distance = GestureUtilities.cosineDistance(sample.vector, vector); } else { distance = GestureUtilities.squaredEuclideanDistance(sample.vector, vector); diff --git a/core/java/android/gesture/LetterRecognizer.java b/core/java/android/gesture/LetterRecognizer.java index 9e801ed435629..580fc26191f75 100644 --- a/core/java/android/gesture/LetterRecognizer.java +++ b/core/java/android/gesture/LetterRecognizer.java @@ -23,6 +23,7 @@ import android.util.Log; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -31,10 +32,9 @@ import java.util.HashMap; import static android.gesture.GestureConstants.LOG_TAG; public class LetterRecognizer { - public final static int RECOGNIZER_LATIN_LOWERCASE = 0; static final String GESTURE_FILE_NAME = "letters.gestures"; - private final static int ADJUST_RANGE = 3; + private final static int ADJUST_RANGE = 3; private SigmoidUnit[] mHiddenLayer; private SigmoidUnit[] mOutputLayer; @@ -42,8 +42,8 @@ public class LetterRecognizer { private final String[] mClasses; private final int mPatchSize; - - private GestureLibrary mGestureLibrary; + + private GestureLibrary mGestureStore; private final Comparator mComparator = new PredictionComparator(); @@ -69,15 +69,6 @@ public class LetterRecognizer { } } - public static LetterRecognizer getLetterRecognizer(Context context, int type) { - switch (type) { - case RECOGNIZER_LATIN_LOWERCASE: { - return createFromResource(context, com.android.internal.R.raw.latin_lowercase); - } - } - return null; - } - private LetterRecognizer(int numOfInput, int numOfHidden, String[] classes) { mPatchSize = (int) Math.sqrt(numOfInput); mHiddenLayer = new SigmoidUnit[numOfHidden]; @@ -137,14 +128,18 @@ public class LetterRecognizer { return output; } - private static LetterRecognizer createFromResource(Context context, int resourceID) { + static LetterRecognizer createFromResource(Context context, int resourceID) { final Resources resources = context.getResources(); + final InputStream stream = resources.openRawResource(resourceID); + return createFromStream(stream); + } + static LetterRecognizer createFromStream(InputStream stream) { DataInputStream in = null; LetterRecognizer classifier = null; try { - in = new DataInputStream(new BufferedInputStream(resources.openRawResource(resourceID), + in = new DataInputStream(new BufferedInputStream(stream, GestureConstants.IO_BUFFER_SIZE)); final int version = in.readShort(); @@ -206,49 +201,49 @@ public class LetterRecognizer { } /** - * TODO: Publish this API once we figure out where we should save the personzlied + * TODO: Publish this API once we figure out where we should save the personalized * gestures, and how to do so across all apps * * @hide */ public boolean save() { - if (mGestureLibrary != null) { - return mGestureLibrary.save(); + if (mGestureStore != null) { + return mGestureStore.save(); } return false; } /** - * TODO: Publish this API once we figure out where we should save the personzlied + * TODO: Publish this API once we figure out where we should save the personalized * gestures, and how to do so across all apps * * @hide */ public void setPersonalizationEnabled(boolean enabled) { if (enabled) { - mGestureLibrary = new GestureLibrary(GESTURE_FILE_NAME); - mGestureLibrary.setSequenceType(GestureLibrary.SEQUENCE_INVARIANT); - mGestureLibrary.load(); + mGestureStore = GestureLibraries.fromFile(GESTURE_FILE_NAME); + mGestureStore.setSequenceType(GestureStore.SEQUENCE_INVARIANT); + mGestureStore.load(); } else { - mGestureLibrary = null; + mGestureStore = null; } } /** - * TODO: Publish this API once we figure out where we should save the personzlied + * TODO: Publish this API once we figure out where we should save the personalized * gestures, and how to do so across all apps * * @hide */ public void addExample(String letter, Gesture example) { - if (mGestureLibrary != null) { - mGestureLibrary.addGesture(letter, example); + if (mGestureStore != null) { + mGestureStore.addGesture(letter, example); } } - + private void adjustPrediction(Gesture query, ArrayList predictions) { - if (mGestureLibrary != null) { - final ArrayList results = mGestureLibrary.recognize(query); + if (mGestureStore != null) { + final ArrayList results = mGestureStore.recognize(query); final HashMap topNList = new HashMap(); for (int j = 0; j < ADJUST_RANGE; j++) { diff --git a/core/java/android/gesture/LetterRecognizers.java b/core/java/android/gesture/LetterRecognizers.java new file mode 100644 index 0000000000000..e3f45a0308e13 --- /dev/null +++ b/core/java/android/gesture/LetterRecognizers.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package android.gesture; + +import android.content.Context; +import android.util.Log; +import static android.gesture.GestureConstants.LOG_TAG; +import static android.gesture.LetterRecognizer.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; + +public final class LetterRecognizers { + public final static int RECOGNIZER_LATIN_LOWERCASE = 0; + + private LetterRecognizers() { + } + + public static LetterRecognizer fromType(Context context, int type) { + switch (type) { + case RECOGNIZER_LATIN_LOWERCASE: { + return createFromResource(context, com.android.internal.R.raw.latin_lowercase); + } + } + return null; + } + + public static LetterRecognizer fromResource(Context context, int resourceId) { + return createFromResource(context, resourceId); + } + + public static LetterRecognizer fromFile(String path) { + return fromFile(new File(path)); + } + + public static LetterRecognizer fromFile(File file) { + try { + return createFromStream(new FileInputStream(file)); + } catch (FileNotFoundException e) { + Log.d(LOG_TAG, "Failed to load handwriting data from file " + file, e); + } + return null; + } + + public static LetterRecognizer fromStream(InputStream stream) { + return createFromStream(stream); + } +} diff --git a/core/java/android/os/MemoryFile.java b/core/java/android/os/MemoryFile.java index 76e4f47f8d2b5..65e83c77957a3 100644 --- a/core/java/android/os/MemoryFile.java +++ b/core/java/android/os/MemoryFile.java @@ -18,6 +18,7 @@ package android.os; import android.util.Log; +import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -35,19 +36,19 @@ import java.io.OutputStream; public class MemoryFile { private static String TAG = "MemoryFile"; - - // returns fd - private native int native_open(String name, int length); - // returns memory address for ashmem region - private native int native_mmap(int fd, int length); - private native void native_close(int fd); - private native int native_read(int fd, int address, byte[] buffer, - int srcOffset, int destOffset, int count, boolean isUnpinned); - private native void native_write(int fd, int address, byte[] buffer, - int srcOffset, int destOffset, int count, boolean isUnpinned); - private native void native_pin(int fd, boolean pin); - private int mFD; // ashmem file descriptor + private static native FileDescriptor native_open(String name, int length) throws IOException; + // returns memory address for ashmem region + private static native int native_mmap(FileDescriptor fd, int length) throws IOException; + private static native void native_munmap(int addr, int length) throws IOException; + private static native void native_close(FileDescriptor fd); + private static native int native_read(FileDescriptor fd, int address, byte[] buffer, + int srcOffset, int destOffset, int count, boolean isUnpinned) throws IOException; + private static native void native_write(FileDescriptor fd, int address, byte[] buffer, + int srcOffset, int destOffset, int count, boolean isUnpinned) throws IOException; + private static native void native_pin(FileDescriptor fd, boolean pin) throws IOException; + + private FileDescriptor mFD; // ashmem file descriptor private int mAddress; // address of ashmem memory private int mLength; // total length of our ashmem region private boolean mAllowPurging = false; // true if our ashmem region is unpinned @@ -57,8 +58,9 @@ public class MemoryFile * * @param name optional name for the file (can be null). * @param length of the memory file in bytes. + * @throws IOException if the memory file could not be created. */ - public MemoryFile(String name, int length) { + public MemoryFile(String name, int length) throws IOException { mLength = length; mFD = native_open(name, length); mAddress = native_mmap(mFD, length); @@ -68,15 +70,40 @@ public class MemoryFile * Closes and releases all resources for the memory file. */ public void close() { - if (mFD > 0) { + deactivate(); + if (!isClosed()) { native_close(mFD); - mFD = 0; } } + private void deactivate() { + if (!isDeactivated()) { + try { + native_munmap(mAddress, mLength); + mAddress = 0; + } catch (IOException ex) { + Log.e(TAG, ex.toString()); + } + } + } + + /** + * Checks whether the memory file has been deactivated. + */ + private boolean isDeactivated() { + return mAddress == 0; + } + + /** + * Checks whether the memory file has been closed. + */ + private boolean isClosed() { + return !mFD.valid(); + } + @Override protected void finalize() { - if (mFD > 0) { + if (!isClosed()) { Log.e(TAG, "MemoryFile.finalize() called while ashmem still open"); close(); } @@ -131,7 +158,6 @@ public class MemoryFile @return OutputStream */ public OutputStream getOutputStream() { - return new MemoryOutputStream(); } @@ -144,9 +170,13 @@ public class MemoryFile * @param destOffset offset into the byte array buffer to read into. * @param count number of bytes to read. * @return number of bytes read. + * @throws IOException if the memory file has been purged or deactivated. */ public int readBytes(byte[] buffer, int srcOffset, int destOffset, int count) throws IOException { + if (isDeactivated()) { + throw new IOException("Can't read from deactivated memory file."); + } if (destOffset < 0 || destOffset > buffer.length || count < 0 || count > buffer.length - destOffset || srcOffset < 0 || srcOffset > mLength @@ -164,9 +194,13 @@ public class MemoryFile * @param srcOffset offset into the byte array buffer to write from. * @param destOffset offset into the memory file to write to. * @param count number of bytes to write. + * @throws IOException if the memory file has been purged or deactivated. */ public void writeBytes(byte[] buffer, int srcOffset, int destOffset, int count) throws IOException { + if (isDeactivated()) { + throw new IOException("Can't write to deactivated memory file."); + } if (srcOffset < 0 || srcOffset > buffer.length || count < 0 || count > buffer.length - srcOffset || destOffset < 0 || destOffset > mLength diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index abd6934a86b39..7d03801d7bd10 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -151,6 +151,9 @@ public class CallLog { int presentation, int callType, long start, int duration) { final ContentResolver resolver = context.getContentResolver(); + // TODO(Moto): Which is correct: original code, this only changes the + // number if the number is empty and never changes the caller info name. + if (false) { if (TextUtils.isEmpty(number)) { if (presentation == Connection.PRESENTATION_RESTRICTED) { number = CallerInfo.PRIVATE_NUMBER; @@ -160,7 +163,22 @@ public class CallLog { number = CallerInfo.UNKNOWN_NUMBER; } } + } else { + // NEWCODE: From Motorola + //If this is a private number then set the number to Private, otherwise check + //if the number field is empty and set the number to Unavailable + if (presentation == Connection.PRESENTATION_RESTRICTED) { + number = CallerInfo.PRIVATE_NUMBER; + ci.name = ""; + } else if (presentation == Connection.PRESENTATION_PAYPHONE) { + number = CallerInfo.PAYPHONE_NUMBER; + ci.name = ""; + } else if (TextUtils.isEmpty(number) || presentation == Connection.PRESENTATION_UNKNOWN) { + number = CallerInfo.UNKNOWN_NUMBER; + ci.name = ""; + } + } ContentValues values = new ContentValues(5); values.put(NUMBER, number); diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java new file mode 100644 index 0000000000000..cc71547c83843 --- /dev/null +++ b/core/java/android/provider/ContactsContract.java @@ -0,0 +1,616 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.provider; + +import android.graphics.BitmapFactory; +import android.net.Uri; + +/** + * The contract between the contacts provider and applications. Contains definitions + * for the supported URIs and columns. + * + * @hide + */ +public final class ContactsContract { + /** The authority for the contacts provider */ + public static final String AUTHORITY = "com.android.contacts"; + /** A content:// style uri to the authority for the contacts provider */ + public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY); + + public interface AggregatesColumns { + /** + * The display name for the contact. + *

Type: TEXT

+ */ + public static final String DISPLAY_NAME = "display_name"; + + /** + * The number of times a person has been contacted + *

Type: INTEGER

+ */ + public static final String TIMES_CONTACTED = "times_contacted"; + + /** + * The last time a person was contacted. + *

Type: INTEGER

+ */ + public static final String LAST_TIME_CONTACTED = "last_time_contacted"; + + /** + * Is the contact starred? + *

Type: INTEGER (boolean)

+ */ + public static final String STARRED = "starred"; + + /** + * Reference to the row in the data table holding the primary phone number. + *

Type: INTEGER REFERENCES data(_id)

+ */ + public static final String PRIMARY_PHONE_ID = "primary_phone_id"; + + /** + * Reference to the row in the data table holding the primary email address. + *

Type: INTEGER REFERENCES data(_id)

+ */ + public static final String PRIMARY_EMAIL_ID = "primary_email_id"; + + /** + * Reference to the row in the data table holding the photo. + *

Type: INTEGER REFERENCES data(_id)

+ */ + public static final String PHOTO_ID = "photo_id"; + + /** + * Reference to a row containing custom ringtone and send to voicemail information. + *

Type: INTEGER REFERENCES data(_id)

+ */ + public static final String CUSTOM_RINGTONE_ID = "custom_ringtone_id"; + } + + /** + * Constants for the aggregates table, which contains a record per group + * of contact representing the same person. + */ + public static final class Aggregates implements BaseColumns, AggregatesColumns { + /** + * This utility class cannot be instantiated + */ + private Aggregates() {} + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "aggregates"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of + * people. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person_aggregate"; + + /** + * The MIME type of a {@link #CONTENT_URI} subdirectory of a single + * person. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person_aggregate"; + + /** + * A sub-directory of a single contact aggregate that contains all of their + * {@link Data} rows. + */ + public static final class Data implements BaseColumns, DataColumns { + /** + * no public constructor since this is a utility class + */ + private Data() {} + + /** + * The directory twig for this sub-table + */ + public static final String CONTENT_DIRECTORY = "data"; + } + } + + + /** + * Constants for the contacts table, which contains the base contact information. + */ + public static final class Contacts implements BaseColumns { + /** + * This utility class cannot be instantiated + */ + private Contacts() {} + + /** + * A reference to the {@link Aggregates#_ID} that this data belongs to. + */ + public static final String AGGREGATE_ID = "aggregate_id"; + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contacts"); + + /** + * The content:// style URL for filtering people by email address. The + * filter argument should be passed as an additional path segment after + * this URI. + * + * @hide + */ + public static final Uri CONTENT_FILTER_EMAIL_URI = Uri.withAppendedPath(CONTENT_URI, "filter_email"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of + * people. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person"; + + /** + * The MIME type of a {@link #CONTENT_URI} subdirectory of a single + * person. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person"; + + /** + * A sub-directory of a single contact that contains all of their {@link Data} rows. + * To access this directory append + */ + public static final class Data implements BaseColumns, DataColumns { + /** + * no public constructor since this is a utility class + */ + private Data() {} + + /** + * The directory twig for this sub-table + */ + public static final String CONTENT_DIRECTORY = "data"; + } + } + + private interface DataColumns { + /** + * The package name that defines this type of data. + */ + public static final String PACKAGE = "package"; + + /** + * The mime-type of the item represented by this row. + */ + public static final String MIMETYPE = "mimetype"; + + /** + * A reference to the {@link android.provider.ContactsContract.Contacts#_ID} + * that this data belongs to. + */ + public static final String CONTACT_ID = "contact_id"; + + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA1 = "data1"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA2 = "data2"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA3 = "data3"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA4 = "data4"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA5 = "data5"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA6 = "data6"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA7 = "data7"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA8 = "data8"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA9 = "data9"; + /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + public static final String DATA10 = "data10"; + } + + /** + * Constants for the data table, which contains data points tied to a contact. + * For example, a phone number or email address. Each row in this table contains a type + * definition and some generic columns. Each data type can define the meaning for each of + * the generic columns. + */ + public static final class Data implements BaseColumns, DataColumns { + /** + * This utility class cannot be instantiated + */ + private Data() {} + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "data"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of data. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data"; + } + + /** + * A table that represents the result of looking up a phone number, for example for caller ID. + * The table joins that data row for the phone number with the contact that owns the number. + * To perform a lookup you must append the number you want to find to {@link #CONTENT_URI}. + */ + public static final class PhoneLookup implements BaseColumns, DataColumns, AggregatesColumns { + /** + * This utility class cannot be instantiated + */ + private PhoneLookup() {} + + /** + * The content:// style URI for this table. Append the phone number you want to lookup + * to this URI and query it to perform a lookup. For example: + * + * {@code + * Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_URI, phoneNumber); + * } + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "phone_lookup"); + } + + /** + * Container for definitions of common data types stored in the {@link Data} table. + */ + public static final class CommonDataKinds { + /** + * The {@link Data#PACKAGE} value for common data that should be shown + * using a default style. + */ + public static final String PACKAGE_COMMON = "common"; + + /** + * Columns common across the specific types. + */ + private interface BaseCommonColumns { + /** + * The package name that defines this type of data. + */ + public static final String PACKAGE = "package"; + + /** + * The mime-type of the item represented by this row. + */ + public static final String MIMETYPE = "mimetype"; + + /** + * A reference to the {@link android.provider.ContactsContract.Contacts#_ID} that this + * data belongs to. + */ + public static final String CONTACT_ID = "contact_id"; + } + + /** + * Columns common across the specific types. + */ + private interface CommonColumns { + /** + * The type of data, for example Home or Work. + *

Type: INTEGER

+ */ + public static final String TYPE = "data1"; + + /** + * The user defined label for the the contact method. + *

Type: TEXT

+ */ + public static final String LABEL = "data2"; + + /** + * The data for the contact method. + *

Type: TEXT

+ */ + public static final String DATA = "data3"; + + /** + * Whether this is the primary entry of its kind for the contact it belongs to + *

Type: INTEGER (if set, non-0 means true)

+ */ + public static final String ISPRIMARY = "data4"; + } + + /** + * Parts of the name. + */ + public static final class StructuredName { + private StructuredName() {} + + /** Mime-type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name"; + + /** + * The contact's honorific prefix, e.g. "Sir" + */ + public static final String PREFIX = "data1"; + + /** + * The given name for the contact. + *

Type: TEXT

+ */ + public static final String GIVEN_NAME = "data2"; + + /** + * The contact's middle name + *

Type: TEXT

+ */ + public static final String MIDDLE_NAME = "data3"; + + /** + * The family name for the contact. + *

Type: TEXT

+ */ + public static final String FAMILY_NAME = "data4"; + + /** + * The contact's honorific suffix, e.g. "Jr" + */ + public static final String SUFFIX = "data5"; + + /** + * The phonetic version of the given name for the contact. + *

Type: TEXT

+ */ + public static final String PHONETIC_GIVEN_NAME = "data6"; + + /** + * The phonetic version of the additional name for the contact. + *

Type: TEXT

+ */ + public static final String PHONETIC_MIDDLE_NAME = "data7"; + + /** + * The phonetic version of the family name for the contact. + *

Type: TEXT

+ */ + public static final String PHONETIC_FAMILY_NAME = "data8"; + + /** + * The name that should be used to display the contact. + *

Type: TEXT

+ */ + public static final String DISPLAY_NAME = "data9"; + } + + /** + * A nickname. + */ + public static final class Nickname { + private Nickname() {} + + /** Mime-type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname"; + + /** + * The type of data, for example Home or Work. + *

Type: INTEGER

+ */ + public static final String TYPE = "data1"; + + public static final int TYPE_CUSTOM = 1; + public static final int TYPE_DEFAULT = 2; + public static final int TYPE_OTHER_NAME = 3; + public static final int TYPE_MAINDEN_NAME = 4; + public static final int TYPE_SHORT_NAME = 5; + public static final int TYPE_INITIALS = 6; + + /** + * The user provided label, only used if TYPE is {@link #TYPE_CUSTOM}. + *

Type: TEXT

+ */ + public static final String LABEL = "data2"; + + /** + * The name itself + */ + public static final String NAME = "data3"; + } + + /** + * Common data definition for telephone numbers. + */ + public static final class Phone implements BaseCommonColumns, CommonColumns { + private Phone() {} + + /** Mime-type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone"; + + public static final int TYPE_CUSTOM = 0; + public static final int TYPE_HOME = 1; + public static final int TYPE_MOBILE = 2; + public static final int TYPE_WORK = 3; + public static final int TYPE_FAX_WORK = 4; + public static final int TYPE_FAX_HOME = 5; + public static final int TYPE_PAGER = 6; + public static final int TYPE_OTHER = 7; + + /** + * The phone number as the user entered it. + *

Type: TEXT

+ */ + public static final String NUMBER = "data3"; + + } + + /** + * Common data definition for email addresses. + */ + public static final class Email implements BaseCommonColumns, CommonColumns { + private Email() {} + + /** Mime-type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email"; + + public static final int TYPE_CUSTOM = 0; + public static final int TYPE_HOME = 1; + public static final int TYPE_WORK = 2; + public static final int TYPE_OTHER = 3; + + } + + /** + * Common data definition for postal addresses. + */ + public static final class Postal implements BaseCommonColumns, CommonColumns { + private Postal() {} + + /** Mime-type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/postal-address"; + + public static final int TYPE_CUSTOM = 0; + public static final int TYPE_HOME = 1; + public static final int TYPE_WORK = 2; + public static final int TYPE_OTHER = 3; + } + + /** + * Common data definition for IM addresses. + */ + public static final class Im implements BaseCommonColumns, CommonColumns { + private Im() {} + + /** Mime-type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im"; + + public static final int TYPE_CUSTOM = 0; + public static final int TYPE_HOME = 1; + public static final int TYPE_WORK = 2; + public static final int TYPE_OTHER = 3; + + public static final String PROTOCOL = "data5"; + + /** + * The predefined IM protocol types. The protocol can either be non-present, one + * of these types, or a free-form string. These cases are encoded in the PROTOCOL + * column as: + * - null + * - pre: + * - custom: + */ + public static final int PROTOCOL_AIM = 0; + public static final int PROTOCOL_MSN = 1; + public static final int PROTOCOL_YAHOO = 2; + public static final int PROTOCOL_SKYPE = 3; + public static final int PROTOCOL_QQ = 4; + public static final int PROTOCOL_GOOGLE_TALK = 5; + public static final int PROTOCOL_ICQ = 6; + public static final int PROTOCOL_JABBER = 7; + } + + /** + * Common data definition for organizations. + */ + public static final class Organization implements BaseCommonColumns { + private Organization() {} + + /** Mime-type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization"; + + /** + * The type of data, for example Home or Work. + *

Type: INTEGER

+ */ + public static final String TYPE = "data1"; + + public static final int TYPE_CUSTOM = 0; + public static final int TYPE_HOME = 1; + public static final int TYPE_WORK = 2; + public static final int TYPE_OTHER = 3; + + /** + * The user provided label, only used if TYPE is {@link #TYPE_CUSTOM}. + *

Type: TEXT

+ */ + public static final String LABEL = "data2"; + + /** + * The company as the user entered it. + *

Type: TEXT

+ */ + public static final String COMPANY = "data3"; + + /** + * The position title at this company as the user entered it. + *

Type: TEXT

+ */ + public static final String TITLE = "data4"; + + /** + * Whether this is the primary organization + *

Type: INTEGER (if set, non-0 means true)

+ */ + public static final String ISPRIMARY = "data5"; + + } + + /** + * Photo of the contact. + */ + public static final class Photo implements BaseCommonColumns { + private Photo() {} + + /** Mime-type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo"; + + /** + * Thumbnail photo of the contact. This is the raw bytes of an image + * that could be inflated using {@link BitmapFactory}. + *

+ * Type: BLOB + */ + public static final String PHOTO = "data1"; + } + + /** + * Notes about the contact. + */ + public static final class Note implements BaseCommonColumns { + private Note() {} + + /** Mime-type used when storing this in data table. */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note"; + + /** + * The note text. + *

Type: TEXT

+ */ + public static final String NOTE = "data1"; + } + + public static final class CustomRingtone implements BaseCommonColumns { + private CustomRingtone() {} + + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/custom_ringtone"; + + /** + * Whether to send the number to voicemail. + *

Type: INTEGER (if set, non-0 means true)

+ */ + public static final String SEND_TO_VOICEMAIL = "data1"; + + /** + * The ringtone uri. + *

Type: TEXT

+ */ + public static final String RINGTONE_URI = "data2"; + } + } + +} diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index b2bdc6de269ce..b4338596ef620 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2854,12 +2854,12 @@ public final class Settings { * out without asking for use permit, to limit the un-authorized SMS * usage. */ - public static final String SMS_OUTGOING_CEHCK_INTERVAL_MS = + public static final String SMS_OUTGOING_CHECK_INTERVAL_MS = "sms_outgoing_check_interval_ms"; /** * The number of outgoing SMS sent without asking for user permit - * (of {@link #SMS_OUTGOING_CEHCK_INTERVAL_MS} + * (of {@link #SMS_OUTGOING_CHECK_INTERVAL_MS} */ public static final String SMS_OUTGOING_CEHCK_MAX_COUNT = "sms_outgoing_check_max_count"; diff --git a/core/java/android/provider/SocialContract.java b/core/java/android/provider/SocialContract.java new file mode 100644 index 0000000000000..d4a9c489f72c8 --- /dev/null +++ b/core/java/android/provider/SocialContract.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.provider; + +import android.graphics.BitmapFactory; +import android.net.Uri; + +/** + * The contract between the social provider and applications. Contains + * definitions for the supported URIs and columns. + * + * @hide + */ +public class SocialContract { + /** The authority for the social provider */ + public static final String AUTHORITY = "com.android.social"; + + /** A content:// style uri to the authority for the contacts provider */ + public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY); + + private interface ActivitiesColumns { + /** + * The package name that owns this social activity. + *

+ * Type: TEXT + */ + public static final String PACKAGE = "package"; + + /** + * The mime-type of this social activity. + *

+ * Type: TEXT + */ + public static final String MIMETYPE = "mimetype"; + + /** + * Internal raw identifier for this social activity. This field is + * analogous to the atom:id element defined in RFC 4287. + *

+ * Type: TEXT + */ + public static final String RAW_ID = "raw_id"; + + /** + * Reference to another {@link Activities#RAW_ID} that this social activity + * is replying to. This field is analogous to the + * thr:in-reply-to element defined in RFC 4685. + *

+ * Type: TEXT + */ + public static final String IN_REPLY_TO = "in_reply_to"; + + /** + * Reference to the {@link android.provider.ContactsContract.Contacts#_ID} that authored + * this social activity. This field is analogous to the atom:author + * element defined in RFC 4287. + *

+ * Type: INTEGER + */ + public static final String AUTHOR_CONTACT_ID = "author_contact_id"; + + /** + * Optional reference to the {@link android.provider.ContactsContract.Contacts#_ID} this + * social activity is targeted towards. If more than one direct target, this field may + * be left undefined. This field is analogous to the + * activity:target element defined in the Atom Activity + * Extensions Internet-Draft. + *

+ * Type: INTEGER + */ + public static final String TARGET_CONTACT_ID = "target_contact_id"; + + /** + * Timestamp when this social activity was published, in a + * {@link System#currentTimeMillis()} time base. This field is analogous + * to the atom:published element defined in RFC 4287. + *

+ * Type: INTEGER + */ + public static final String PUBLISHED = "published"; + + /** + * Timestamp when the original social activity in a thread was + * published. For activities that have an in-reply-to field specified, the + * content provider will automatically populate this field with the + * timestamp of the original activity. + *

+ * This field is useful for sorting order of activities that keeps together all + * messages in each thread. + *

+ * Type: INTEGER + */ + public static final String THREAD_PUBLISHED = "thread_published"; + + /** + * Title of this social activity. This field is analogous to the + * atom:title element defined in RFC 4287. + *

+ * Type: TEXT + */ + public static final String TITLE = "title"; + + /** + * Summary of this social activity. This field is analogous to the + * atom:summary element defined in RFC 4287. + *

+ * Type: TEXT + */ + public static final String SUMMARY = "summary"; + + /** + * A URI associated this social activity. This field is analogous to the + * atom:link rel="alternate" element defined in RFC 4287. + *

+ * Type: TEXT + */ + public static final String LINK = "link"; + + /** + * Optional thumbnail specific to this social activity. This is the raw + * bytes of an image that could be inflated using {@link BitmapFactory}. + *

+ * Type: BLOB + */ + public static final String THUMBNAIL = "thumbnail"; + } + + public static final class Activities implements BaseColumns, ActivitiesColumns { + /** + * This utility class cannot be instantiated + */ + private Activities() { + } + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "activities"); + + /** + * The content:// style URI for this table filtered to the set of social activities + * authored by a specific {@link android.provider.ContactsContract.Contacts#_ID}. + */ + public static final Uri CONTENT_AUTHORED_BY_URI = + Uri.withAppendedPath(CONTENT_URI, "authored_by"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of social + * activities. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/activity"; + + /** + * The MIME type of a {@link #CONTENT_URI} subdirectory of a single + * social activity. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/activity"; + } + +} diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index a4145c487696b..4078fa6d5a734 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -465,6 +465,24 @@ public final class Telephony { * Contains info about SMS related Intents that are broadcast. */ public static final class Intents { + /** + * Set by BroadcastReceiver. Indicates the message was handled + * successfully. + */ + public static final int RESULT_SMS_HANDLED = 1; + + /** + * Set by BroadcastReceiver. Indicates a generic error while + * processing the message. + */ + public static final int RESULT_SMS_GENERIC_ERROR = 2; + + /** + * Set by BroadcastReceiver. Indicates insufficient memory to store + * the message. + */ + public static final int RESULT_SMS_OUT_OF_MEMORY = 3; + /** * Broadcast Action: A new text based SMS message has been received * by the device. The intent will have the following extra @@ -476,7 +494,10 @@ public final class Telephony { * * *

The extra values can be extracted using - * {@link #getMessagesFromIntent(Intent)}

+ * {@link #getMessagesFromIntent(Intent)}.

+ * + *

If a BroadcastReceiver encounters an error while processing + * this intent it should set the result code appropriately.

*/ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String SMS_RECEIVED_ACTION = @@ -493,7 +514,10 @@ public final class Telephony { * * *

The extra values can be extracted using - * {@link #getMessagesFromIntent(Intent)}

+ * {@link #getMessagesFromIntent(Intent)}.

+ * + *

If a BroadcastReceiver encounters an error while processing + * this intent it should set the result code appropriately.

*/ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String DATA_SMS_RECEIVED_ACTION = @@ -510,6 +534,9 @@ public final class Telephony { *
  • pduType (Integer) - The WAP PDU type
  • *
  • data - The data payload of the message
  • * + * + *

    If a BroadcastReceiver encounters an error while processing + * this intent it should set the result code appropriately.

    */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WAP_PUSH_RECEIVED_ACTION = diff --git a/core/java/android/speech/IRecognitionListener.aidl b/core/java/android/speech/IRecognitionListener.aidl index 6ed32b502b424..b4abfda30aed0 100644 --- a/core/java/android/speech/IRecognitionListener.aidl +++ b/core/java/android/speech/IRecognitionListener.aidl @@ -17,6 +17,7 @@ package android.speech; import android.os.Bundle; +import android.speech.RecognitionResult; /** * Listener for speech recognition events, used with RecognitionService. @@ -43,13 +44,19 @@ interface IRecognitionListener { /** Called after the user stops speaking. */ void onEndOfSpeech(); - /** A network or recognition error occurred. */ - void onError(in String error); + /** + * A network or recognition error occurred. + * TODO: right now, the error code is given in voice search package + * (vendor/google/apps/src/com/google/android/voicesearch/speechservice/SpeechServiceListener.java) + * we need to find a place to define common error code. + */ + void onError(in int error); /** - * Called when recognition transcripts are ready. - * results: an ordered list of the most likely transcripts (N-best list). - * @hide + * Called when recognition results are ready. + * @param results: an ordered list of the most likely results (N-best list). + * @param key: a key associated with the results. The same results can + * be retrieved asynchronously later using the key, if available. */ - void onResults(in List results); + void onResults(in List results, long key); } diff --git a/core/java/android/speech/IRecognitionService.aidl b/core/java/android/speech/IRecognitionService.aidl index 36d12e9aae643..a18c380c9e707 100644 --- a/core/java/android/speech/IRecognitionService.aidl +++ b/core/java/android/speech/IRecognitionService.aidl @@ -18,6 +18,7 @@ package android.speech; import android.content.Intent; import android.speech.IRecognitionListener; +import android.speech.RecognitionResult; // A Service interface to speech recognition. Call startListening when // you want to begin capturing audio; RecognitionService will automatically @@ -29,6 +30,8 @@ interface IRecognitionService { // see RecognizerIntent.java for constants used to specify the intent. void startListening(in Intent recognizerIntent, in IRecognitionListener listener); + + List getRecognitionResults(in long key); void cancel(); } diff --git a/libs/utils/executablepath_linux.cpp b/core/java/android/speech/RecognitionResult.aidl similarity index 63% rename from libs/utils/executablepath_linux.cpp rename to core/java/android/speech/RecognitionResult.aidl index b8d2a3d6fbc97..59e53ab86fd18 100644 --- a/libs/utils/executablepath_linux.cpp +++ b/core/java/android/speech/RecognitionResult.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,17 +14,6 @@ * limitations under the License. */ -#include -#include -#include -#include -#include - -void executablepath(char exe[PATH_MAX]) -{ - char proc[100]; - sprintf(proc, "/proc/%d/exe", getpid()); - - int err = readlink(proc, exe, PATH_MAX); -} +package android.speech; +parcelable RecognitionResult; diff --git a/core/java/android/speech/RecognitionResult.java b/core/java/android/speech/RecognitionResult.java new file mode 100644 index 0000000000000..c3ac48404f6ee --- /dev/null +++ b/core/java/android/speech/RecognitionResult.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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.speech; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * RecognitionResult is a passive object that stores a single recognized + * query and its search result. + * TODO: revisit and improve. May be we should have a separate result + * object for each type, and put them (type/value) in bundle? + * + * {@hide} + */ +public class RecognitionResult implements Parcelable { + + /** + * Type of the recognition results. + */ + public static final int RAW_RECOGNITION_RESULT = 0; + public static final int WEB_SEARCH_RESULT = 1; + public static final int CONTACT_RESULT = 2; + + /** + * A factory method to create a raw RecognitionResult + * + * @param sentence the recognized text. + */ + public static RecognitionResult newRawRecognitionResult(String sentence) { + return new RecognitionResult(RAW_RECOGNITION_RESULT, sentence, null, null); + } + + /** + * A factory method to create RecognitionResult for contacts. + * + * @param contact the contact name. + * @param phoneType the phone type. + */ + public static RecognitionResult newContactResult(String contact, int phoneType) { + return new RecognitionResult(CONTACT_RESULT, contact, phoneType); + } + + /** + * A factory method to create a RecognitionResult for Web Search Query. + * + * @param query the query string. + * @param html the html page of the search result. + * @param url the url that performs the search with the query. + */ + public static RecognitionResult newWebResult(String query, String html, String url) { + return new RecognitionResult(WEB_SEARCH_RESULT, query, html, url); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + + public RecognitionResult createFromParcel(Parcel in) { + return new RecognitionResult(in); + } + + public RecognitionResult[] newArray(int size) { + return new RecognitionResult[size]; + } + }; + + /** + * Result type. + */ + public final int mResultType; + + /** + * The recognized string when mResultType is WEB_SEARCH_RESULT. + * The name of the contact when mResultType is CONTACT_RESULT. + */ + public final String mText; + + /** + * The HTML result page for the query. If this is null, then the + * application must use the url field to get the HTML result page. + */ + public final String mHtml; + + /** + * The url to get the result page for the query string. The + * application must use this url instead of performing the search + * with the query. + */ + public final String mUrl; + + /** Phone number type. This is valid only when mResultType == CONTACT_RESULT */ + public final int mPhoneType; + + private RecognitionResult(int type, String query, String html, String url) { + mResultType = type; + mText = query; + mHtml = html; + mUrl = url; + mPhoneType = -1; + } + + private RecognitionResult(int type, String query, int at) { + mResultType = type; + mText = query; + mPhoneType = at; + mHtml = null; + mUrl = null; + } + + private RecognitionResult(Parcel in) { + mResultType = in.readInt(); + mText = in.readString(); + mHtml= in.readString(); + mUrl= in.readString(); + mPhoneType = in.readInt(); + } + + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mResultType); + out.writeString(mText); + out.writeString(mHtml); + out.writeString(mUrl); + out.writeInt(mPhoneType); + } + + + @Override + public String toString() { + String resultType[] = { "RAW", "WEB", "CONTACT" }; + return "[type=" + resultType[mResultType] + + ", text=" + mText+ ", mUrl=" + mUrl + ", html=" + mHtml + "]"; + } + + public int describeContents() { + // no special description + return 0; + } +} diff --git a/core/java/android/speech/RecognitionServiceUtil.java b/core/java/android/speech/RecognitionServiceUtil.java index 650c0fd248817..a8c78684f6cdc 100644 --- a/core/java/android/speech/RecognitionServiceUtil.java +++ b/core/java/android/speech/RecognitionServiceUtil.java @@ -21,6 +21,9 @@ import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; +import android.os.RemoteException; +import android.speech.RecognitionResult; +import android.util.Log; import java.util.List; @@ -56,6 +59,11 @@ public class RecognitionServiceUtil { public static final Intent sDefaultIntent = new Intent( RecognizerIntent.ACTION_RECOGNIZE_SPEECH); + // Recognize request parameters + public static final String USE_LOCATION = "useLocation"; + public static final String CONTACT_AUTH_TOKEN = "contactAuthToken"; + + // Bundles public static final String NOISE_LEVEL = "NoiseLevel"; public static final String SIGNAL_NOISE_RATIO = "SignalNoiseRatio"; @@ -72,8 +80,8 @@ public class RecognitionServiceUtil { public void onRmsChanged(float rmsdB) {} public void onBufferReceived(byte[] buf) {} public void onEndOfSpeech() {} - public void onError(String error) {} - public void onResults(List results) {} + public void onError(int error) {} + public void onResults(List results, long key) {} } /** diff --git a/core/java/android/text/method/DialerKeyListener.java b/core/java/android/text/method/DialerKeyListener.java index b121e608b5b54..584e83f53e53d 100644 --- a/core/java/android/text/method/DialerKeyListener.java +++ b/core/java/android/text/method/DialerKeyListener.java @@ -106,7 +106,7 @@ public class DialerKeyListener extends NumberKeyListener */ public static final char[] CHARACTERS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '*', - '+', '-', '(', ')', ',', '/', 'N', '.', ' ' + '+', '-', '(', ')', ',', '/', 'N', '.', ' ', ';' }; private static DialerKeyListener sInstance; diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 8fff64440db86..eef128be6a4ed 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -370,6 +370,9 @@ public class WebView extends AbsoluteLayout // Whether or not to draw the focus ring. private boolean mDrawFocusRing = true; + // true if onPause has been called (and not onResume) + private boolean mIsPaused; + /** * Customizable constant */ @@ -997,7 +1000,7 @@ public class WebView extends AbsoluteLayout /** * If platform notifications are enabled, this should be called - * from onPause() or onStop(). + * from the Activity's onPause() or onStop(). */ public static void disablePlatformNotifications() { Network.disablePlatformNotifications(); @@ -1938,21 +1941,58 @@ public class WebView extends AbsoluteLayout } /** - * Pause all layout, parsing, and javascript timers. This can be useful if - * the WebView is not visible or the application has been paused. + * Pause all layout, parsing, and javascript timers for all webviews. This + * is a global requests, not restricted to just this webview. This can be + * useful if the application has been paused. */ public void pauseTimers() { mWebViewCore.sendMessage(EventHub.PAUSE_TIMERS); } /** - * Resume all layout, parsing, and javascript timers. This will resume - * dispatching all timers. + * Resume all layout, parsing, and javascript timers for all webviews. + * This will resume dispatching all timers. */ public void resumeTimers() { mWebViewCore.sendMessage(EventHub.RESUME_TIMERS); } + /** + * Call this to pause any extra processing associated with this view and + * its associated DOM/plugins/javascript/etc. For example, if the view is + * taken offscreen, this could be called to reduce unnecessary CPU and/or + * network traffic. When the view is again "active", call onResume(). + * + * Note that this differs from pauseTimers(), which affects all views/DOMs + * @hide + */ + public void onPause() { + if (!mIsPaused) { + mIsPaused = true; + mWebViewCore.sendMessage(EventHub.ON_PAUSE); + } + } + + /** + * Call this to balanace a previous call to onPause() + * @hide + */ + public void onResume() { + if (mIsPaused) { + mIsPaused = false; + mWebViewCore.sendMessage(EventHub.ON_RESUME); + } + } + + /** + * Returns true if the view is paused, meaning onPause() was called. Calling + * onResume() sets the paused state back to false. + * @hide + */ + public boolean isPaused() { + return mIsPaused; + } + /** * Clear the resource cache. Note that the cache is per-application, so * this will clear the cache for all WebViews used. diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index e4d08cf38884b..f9bbc313c8e84 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -591,6 +591,8 @@ final class WebViewCore { "TOUCH_UP", // = 140; "TOUCH_EVENT", // = 141; "SET_ACTIVE", // = 142; + "ON_PAUSE", // = 143 + "ON_RESUME", // = 144 }; class EventHub { @@ -647,6 +649,11 @@ final class WebViewCore { // or not, based on whether the WebView has focus. static final int SET_ACTIVE = 142; + // pause/resume activity for just this DOM (unlike pauseTimers, which + // is global) + static final int ON_PAUSE = 143; + static final int ON_RESUME = 144; + // Network-based messaging static final int CLEAR_SSL_PREF_TABLE = 150; @@ -841,6 +848,14 @@ final class WebViewCore { } break; + case ON_PAUSE: + nativePause(); + break; + + case ON_RESUME: + nativeResume(); + break; + case SET_NETWORK_STATE: if (BrowserFrame.sJavaBridge == null) { throw new IllegalStateException("No WebView " + @@ -1750,4 +1765,7 @@ final class WebViewCore { } } + + private native void nativePause(); + private native void nativeResume(); } diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 3c827a0bad9cd..ec021432ba59a 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -52,6 +52,7 @@ import android.gesture.GestureOverlayView; import android.gesture.Gesture; import android.gesture.LetterRecognizer; import android.gesture.Prediction; +import android.gesture.LetterRecognizers; import com.android.internal.R; @@ -94,7 +95,7 @@ public abstract class AbsListView extends AdapterView implements Te public static final int TRANSCRIPT_MODE_NORMAL = 1; /** * The list will automatically scroll to the bottom, no matter what items - * are currently visible. + * are currently visible. * * @see #setTranscriptMode(int) */ @@ -156,7 +157,7 @@ public abstract class AbsListView extends AdapterView implements Te * Indicates the view is in the process of being flung */ static final int TOUCH_MODE_FLING = 4; - + /** * Indicates that the user is currently dragging the fast scroll thumb */ @@ -349,7 +350,7 @@ public abstract class AbsListView extends AdapterView implements Te * bitmap cache after scrolling. */ boolean mScrollingCacheEnabled; - + /** * Whether or not to enable the fast scroll feature on this list */ @@ -422,7 +423,7 @@ public abstract class AbsListView extends AdapterView implements Te * The last CheckForTap runnable we posted, if any */ private Runnable mPendingCheckForTap; - + /** * The last CheckForKeyLongPress runnable we posted, if any */ @@ -576,7 +577,7 @@ public abstract class AbsListView extends AdapterView implements Te int color = a.getColor(R.styleable.AbsListView_cacheColorHint, 0); setCacheColorHint(color); - + boolean enableFastScroll = a.getBoolean(R.styleable.AbsListView_fastScrollEnabled, false); setFastScrollEnabled(enableFastScroll); @@ -605,7 +606,7 @@ public abstract class AbsListView extends AdapterView implements Te mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); mDensityScale = getContext().getResources().getDisplayMetrics().density; } - + /** *

    Sets the type of gestures to use with this list. When gestures are enabled, * that is if the gestures parameter is not {@link #GESTURES_NONE}, @@ -663,7 +664,7 @@ public abstract class AbsListView extends AdapterView implements Te * @see #GESTURES_NONE * @see #GESTURES_JUMP * @see #GESTURES_FILTER - * @see #setGestures(int) + * @see #setGestures(int) */ @ViewDebug.ExportedProperty(mapping = { @ViewDebug.IntToString(from = GESTURES_NONE, to = "NONE"), @@ -737,7 +738,7 @@ public abstract class AbsListView extends AdapterView implements Te mGesturesOverlay.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE); mGesturesOverlay.addOnGesturePerformedListener(new GesturesProcessor()); - mPreviousGesturing = false; + mPreviousGesturing = false; } } @@ -778,10 +779,10 @@ public abstract class AbsListView extends AdapterView implements Te } /** - * Enables fast scrolling by letting the user quickly scroll through lists by - * dragging the fast scroll thumb. The adapter attached to the list may want + * Enables fast scrolling by letting the user quickly scroll through lists by + * dragging the fast scroll thumb. The adapter attached to the list may want * to implement {@link SectionIndexer} if it wishes to display alphabet preview and - * jump between sections of the list. + * jump between sections of the list. * @see SectionIndexer * @see #isFastScrollEnabled() * @param enabled whether or not to enable fast scrolling @@ -799,7 +800,7 @@ public abstract class AbsListView extends AdapterView implements Te } } } - + /** * Returns the current state of the fast scroll feature. * @see #setFastScrollEnabled(boolean) @@ -809,10 +810,10 @@ public abstract class AbsListView extends AdapterView implements Te public boolean isFastScrollEnabled() { return mFastScrollEnabled; } - + /** * If fast scroll is visible, then don't draw the vertical scrollbar. - * @hide + * @hide */ @Override protected boolean isVerticalScrollBarHidden() { @@ -830,11 +831,11 @@ public abstract class AbsListView extends AdapterView implements Te * When smooth scrollbar is disabled, the position and size of the scrollbar thumb * is based solely on the number of items in the adapter and the position of the * visible items inside the adapter. This provides a stable scrollbar as the user - * navigates through a list of items with varying heights. + * navigates through a list of items with varying heights. * * @param enabled Whether or not to enable smooth scrollbar. * - * @see #setSmoothScrollbarEnabled(boolean) + * @see #setSmoothScrollbarEnabled(boolean) * @attr ref android.R.styleable#AbsListView_smoothScrollbar */ public void setSmoothScrollbarEnabled(boolean enabled) { @@ -1142,7 +1143,7 @@ public abstract class AbsListView extends AdapterView implements Te /** * Sets the initial value for the text filter. * @param filterText The text to use for the filter. - * + * * @see #setTextFilterEnabled */ public void setFilterText(String filterText) { @@ -1168,7 +1169,7 @@ public abstract class AbsListView extends AdapterView implements Te } /** - * Returns the list's text filter, if available. + * Returns the list's text filter, if available. * @return the list's text filter or null if filtering isn't enabled */ public CharSequence getTextFilter() { @@ -1177,7 +1178,7 @@ public abstract class AbsListView extends AdapterView implements Te } return null; } - + @Override protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); @@ -1570,7 +1571,7 @@ public abstract class AbsListView extends AdapterView implements Te if (mInstallGesturesOverlay) { installGesturesOverlay(); positionGesturesPopup(); - } else if (mGesturesPopup != null) { + } else if (mGesturesPopup != null && mGesturesPopup.isShowing()) { mGesturesPopup.update(w, h); } } @@ -1740,7 +1741,7 @@ public abstract class AbsListView extends AdapterView implements Te System.arraycopy(state, enabledPos + 1, state, enabledPos, state.length - enabledPos - 1); } - + return state; } @@ -1851,16 +1852,16 @@ public abstract class AbsListView extends AdapterView implements Te */ private class WindowRunnnable { private int mOriginalAttachCount; - + public void rememberWindowAttachCount() { mOriginalAttachCount = getWindowAttachCount(); } - + public boolean sameWindow() { return hasWindowFocus() && getWindowAttachCount() == mOriginalAttachCount; } } - + private class PerformClick extends WindowRunnnable implements Runnable { View mChild; int mClickMotionPosition; @@ -1887,7 +1888,7 @@ public abstract class AbsListView extends AdapterView implements Te final long longPressId = mAdapter.getItemId(mMotionPosition); boolean handled = false; - if (sameWindow() && !mDataChanged) { + if (sameWindow() && !mDataChanged) { handled = performLongPress(child, longPressPosition, longPressId); } if (handled) { @@ -1901,7 +1902,7 @@ public abstract class AbsListView extends AdapterView implements Te } } } - + private class CheckForKeyLongPress extends WindowRunnnable implements Runnable { public void run() { if (isPressed() && mSelectedPosition >= 0) { @@ -1930,7 +1931,7 @@ public abstract class AbsListView extends AdapterView implements Te boolean handled = false; dismissGesturesPopup(); - + if (mOnItemLongClickListener != null) { handled = mOnItemLongClickListener.onItemLongClick(AbsListView.this, child, longPressPosition, longPressId); @@ -2079,7 +2080,7 @@ public abstract class AbsListView extends AdapterView implements Te mTouchMode = TOUCH_MODE_DONE_WAITING; } } else { - mTouchMode = TOUCH_MODE_DONE_WAITING; + mTouchMode = TOUCH_MODE_DONE_WAITING; } } } @@ -2138,7 +2139,7 @@ public abstract class AbsListView extends AdapterView implements Te boolean intercepted = mFastScroller.onTouchEvent(ev); if (intercepted) { return true; - } + } } final int action = ev.getAction(); @@ -2326,10 +2327,10 @@ public abstract class AbsListView extends AdapterView implements Te } setPressed(false); - + // Need to redraw since we probably aren't drawing the selector anymore invalidate(); - + final Handler handler = getHandler(); if (handler != null) { handler.removeCallbacks(mPendingCheckForLongPress); @@ -2373,7 +2374,7 @@ public abstract class AbsListView extends AdapterView implements Te return true; } - + @Override public void draw(Canvas canvas) { super.draw(canvas); @@ -2388,14 +2389,14 @@ public abstract class AbsListView extends AdapterView implements Te int x = (int) ev.getX(); int y = (int) ev.getY(); View v; - + if (mFastScroller != null) { boolean intercepted = mFastScroller.onInterceptTouchEvent(ev); if (intercepted) { return true; } } - + switch (action) { case MotionEvent.ACTION_DOWN: { int motionPosition = findMotionRow(y); @@ -3245,7 +3246,7 @@ public abstract class AbsListView extends AdapterView implements Te } return null; } - + /** * For filtering we proxy an input connection to an internal text editor, * and this allows the proxying to happen. @@ -3254,7 +3255,7 @@ public abstract class AbsListView extends AdapterView implements Te public boolean checkInputConnectionProxy(View view) { return view == mTextFilter; } - + /** * Creates the window for the text filter and populates it with an EditText field; * @@ -3647,7 +3648,7 @@ public abstract class AbsListView extends AdapterView implements Te mCurrentScrap = scrapViews[0]; mScrapViews = scrapViews; } - + public boolean shouldRecycleViewType(int viewType) { return viewType >= 0; } @@ -3862,11 +3863,10 @@ public abstract class AbsListView extends AdapterView implements Te private final char[] mHolder; GesturesProcessor() { - mRecognizer = LetterRecognizer.getLetterRecognizer(getContext(), - LetterRecognizer.RECOGNIZER_LATIN_LOWERCASE); + mRecognizer = LetterRecognizers.fromType(getContext(), + LetterRecognizers.RECOGNIZER_LATIN_LOWERCASE); if (mRecognizer == null) { - dismissGesturesPopup(); - mGestures = GESTURES_NONE; + setGestures(GESTURES_NONE); } if (mGestures == GESTURES_FILTER) { mKeyMap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD); diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 10d8f55cc6cb6..99cf6f8c6b5cd 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -2851,9 +2851,15 @@ public class ListView extends AbsListView { final int first = mFirstPosition; final boolean areAllItemsSelectable = mAreAllItemsSelectable; final ListAdapter adapter = mAdapter; - final boolean isOpaque = isOpaque(); - if (isOpaque && mDividerPaint == null) { + // If the list is opaque *and* the background is not, we want to + // fill a rect where the dividers would be for non-selectable items + // If the list is opaque and the background is also opaque, we don't + // need to draw anything since the background will do it for us + final boolean fillForMissingDividers = isOpaque() && !super.isOpaque(); + + if (fillForMissingDividers && mDividerPaint == null && mIsCacheColorOpaque) { mDividerPaint = new Paint(); + mDividerPaint.setColor(getCacheColorHint()); } final Paint paint = mDividerPaint; @@ -2874,7 +2880,7 @@ public class ListView extends AbsListView { bounds.top = bottom; bounds.bottom = bottom + dividerHeight; drawDivider(canvas, bounds, i); - } else if (isOpaque) { + } else if (fillForMissingDividers) { bounds.top = bottom; bounds.bottom = bottom + dividerHeight; canvas.drawRect(bounds, paint); @@ -2903,7 +2909,7 @@ public class ListView extends AbsListView { // position. Give -1 when there is no child above the // divider. drawDivider(canvas, bounds, i - 1); - } else if (isOpaque) { + } else if (fillForMissingDividers) { bounds.top = top - dividerHeight; bounds.bottom = top; canvas.drawRect(bounds, paint); diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java index dc2c70de92e4b..5bf8035e8ccc5 100644 --- a/core/java/android/widget/TabHost.java +++ b/core/java/android/widget/TabHost.java @@ -87,8 +87,9 @@ public class TabHost extends FrameLayout implements ViewTreeObserver.OnTouchMode /** - *

    Call setup() before adding tabs if loading TabHost using findViewById(). However: You do - * not need to call setup() after getTabHost() in {@link android.app.TabActivity TabActivity}. + *

    Call setup() before adding tabs if loading TabHost using findViewById(). + * However: You do not need to call setup() after getTabHost() + * in {@link android.app.TabActivity TabActivity}. * Example:

    mTabHost = (TabHost)findViewById(R.id.tabhost);
     mTabHost.setup();
    @@ -363,14 +364,14 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
              * 
              * @param tag
              *            Which tab was selected.
    -         * @return The view to distplay the contents of the selected tab.
    +         * @return The view to display the contents of the selected tab.
              */
             View createTabContent(String tag);
         }
     
     
         /**
    -     * A tab has a tab indictor, content, and a tag that is used to keep
    +     * A tab has a tab indicator, content, and a tag that is used to keep
          * track of it.  This builder helps choose among these options.
          *
          * For the tab indicator, your choices are:
    @@ -607,7 +608,7 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
                 }
                 mLaunchedView = wd;
                 
    -            // XXX Set FOCUS_AFTER_DESCENDANTS on embedded activies for now so they can get
    +            // XXX Set FOCUS_AFTER_DESCENDANTS on embedded activities for now so they can get
                 // focus if none of their children have it. They need focus to be able to
                 // display menu items.
                 //
    diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
    index a448ac6d4c692..51f3b025f84dc 100644
    --- a/core/java/com/android/internal/os/BatteryStatsImpl.java
    +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
    @@ -53,7 +53,7 @@ public final class BatteryStatsImpl extends BatteryStats {
         private static final int MAGIC = 0xBA757475; // 'BATSTATS' 
     
         // Current on-disk Parcel version
    -    private static final int VERSION = 36;
    +    private static final int VERSION = 37;
     
         private final File mFile;
         private final File mBackupFile;
    @@ -3014,6 +3014,8 @@ public final class BatteryStatsImpl extends BatteryStats {
                 
                 u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
    +            u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
    +            u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
                 u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL);
     
    diff --git a/core/jni/android_os_MemoryFile.cpp b/core/jni/android_os_MemoryFile.cpp
    index edf7dc45991b9..9450e158dee55 100644
    --- a/core/jni/android_os_MemoryFile.cpp
    +++ b/core/jni/android_os_MemoryFile.cpp
    @@ -26,7 +26,7 @@
     
     namespace android {
     
    -static jint android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length)
    +static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length)
     {
         const char* namestr = (name ? env->GetStringUTFChars(name, NULL) : NULL);
     
    @@ -37,28 +37,45 @@ static jint android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name,
         if (name)
             env->ReleaseStringUTFChars(name, namestr);
     
    -    if (result < 0)
    +    if (result < 0) {
             jniThrowException(env, "java/io/IOException", "ashmem_create_region failed");
    -    return result;
    +	return NULL;
    +    }
    +
    +    return jniCreateFileDescriptor(env, result);
     }
     
    -static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jint fd, jint length)
    +static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jobject fileDescriptor,
    +        jint length)
     {
    +    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
         jint result = (jint)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
         if (!result)
             jniThrowException(env, "java/io/IOException", "mmap failed");
         return result;
     }
     
    -static void android_os_MemoryFile_close(JNIEnv* env, jobject clazz, jint fd)
    +static void android_os_MemoryFile_munmap(JNIEnv* env, jobject clazz, jint addr, jint length)
     {
    -    close(fd);
    +    int result = munmap((void *)addr, length);
    +    if (result < 0)
    +        jniThrowException(env, "java/io/IOException", "munmap failed");
    +}
    +
    +static void android_os_MemoryFile_close(JNIEnv* env, jobject clazz, jobject fileDescriptor)
    +{
    +    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
    +    if (fd >= 0) {
    +        jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
    +        close(fd);
    +    }
     }
     
     static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz,
    -        jint fd, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
    +        jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
             jint count, jboolean unpinned)
     {
    +    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
         if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
             ashmem_unpin_region(fd, 0, 0);
             jniThrowException(env, "java/io/IOException", "ashmem region was purged");
    @@ -76,9 +93,10 @@ static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz,
     }
     
     static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz,
    -        jint fd, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
    +        jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
             jint count, jboolean unpinned)
     {
    +    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
         if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
             ashmem_unpin_region(fd, 0, 0);
             jniThrowException(env, "java/io/IOException", "ashmem region was purged");
    @@ -95,8 +113,9 @@ static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz,
         return count;
     }
     
    -static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jint fd, jboolean pin)
    +static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jobject fileDescriptor, jboolean pin)
     {
    +    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
         int result = (pin ? ashmem_pin_region(fd, 0, 0) : ashmem_unpin_region(fd, 0, 0));
         if (result < 0) {
             jniThrowException(env, "java/io/IOException", NULL);
    @@ -104,12 +123,13 @@ static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jint fd, jbool
     }
     
     static const JNINativeMethod methods[] = {
    -	{"native_open",  "(Ljava/lang/String;I)I", (void*)android_os_MemoryFile_open},
    -    {"native_mmap",  "(II)I", (void*)android_os_MemoryFile_mmap},
    -    {"native_close", "(I)V", (void*)android_os_MemoryFile_close},
    -    {"native_read",  "(II[BIIIZ)I", (void*)android_os_MemoryFile_read},
    -    {"native_write", "(II[BIIIZ)V", (void*)android_os_MemoryFile_write},
    -    {"native_pin",   "(IZ)V", (void*)android_os_MemoryFile_pin},
    +    {"native_open",  "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_MemoryFile_open},
    +    {"native_mmap",  "(Ljava/io/FileDescriptor;I)I", (void*)android_os_MemoryFile_mmap},
    +    {"native_munmap", "(II)V", (void*)android_os_MemoryFile_munmap},
    +    {"native_close", "(Ljava/io/FileDescriptor;)V", (void*)android_os_MemoryFile_close},
    +    {"native_read",  "(Ljava/io/FileDescriptor;I[BIIIZ)I", (void*)android_os_MemoryFile_read},
    +    {"native_write", "(Ljava/io/FileDescriptor;I[BIIIZ)V", (void*)android_os_MemoryFile_write},
    +    {"native_pin",   "(Ljava/io/FileDescriptor;Z)V", (void*)android_os_MemoryFile_pin},
     };
     
     static const char* const kClassPathName = "android/os/MemoryFile";
    diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
    index b97e07b2c1055..0a24bb782313f 100644
    --- a/core/res/AndroidManifest.xml
    +++ b/core/res/AndroidManifest.xml
    @@ -644,6 +644,13 @@
             android:description="@string/permdesc_changeWifiState"
             android:label="@string/permlab_changeWifiState" />
     
    +    
    +    
    +
         
         
     
    +    
    +    allow Wi-Fi Multicast
    +      reception
    +    
    +    Allows an application to
    +      receive packets not directly addressed to your device.  This can be
    +      useful when discovering services offered near by.  It uses more power
    +      than the non-multicast mode.
    +
         
         bluetooth administration
         
    diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
    index 490abde075d45..72402d0a1f551 100644
    --- a/core/res/res/values/styles.xml
    +++ b/core/res/res/values/styles.xml
    @@ -177,7 +177,7 @@
             #48ffff00
             420
             150
    -        30.0
    +        50.0
             0.275
             40.0
             true
    diff --git a/docs/html/shareables/icon_templates-v1.0.zip b/docs/html/shareables/icon_templates-v1.0.zip
    index 3e64f9aacd50c..94fbcdcea6cc4 100644
    Binary files a/docs/html/shareables/icon_templates-v1.0.zip and b/docs/html/shareables/icon_templates-v1.0.zip differ
    diff --git a/include/tts/TtsEngine.h b/include/tts/TtsEngine.h
    index 06f3820030555..bf629958ba78c 100644
    --- a/include/tts/TtsEngine.h
    +++ b/include/tts/TtsEngine.h
    @@ -53,7 +53,8 @@ enum tts_result {
         TTS_FEATURE_UNSUPPORTED     = -2,
         TTS_VALUE_INVALID           = -3,
         TTS_PROPERTY_UNSUPPORTED    = -4,
    -    TTS_PROPERTY_SIZE_TOO_SMALL = -5
    +    TTS_PROPERTY_SIZE_TOO_SMALL = -5,
    +    TTS_MISSING_RESOURCES       = -6
     };
     
     class TtsEngine
    diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
    index 49b01293fedf4..9783e54769142 100644
    --- a/libs/audioflinger/AudioFlinger.cpp
    +++ b/libs/audioflinger/AudioFlinger.cpp
    @@ -824,19 +824,22 @@ void AudioFlinger::handleForcedSpeakerRoute(int command)
             {
                 AutoMutex lock(mHardwareLock);
                 if (mForcedSpeakerCount++ == 0) {
    -                mRouteRestoreTime = 0;
    -                mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC);
    -                if (mForcedRoute == 0 && !(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
    -                    LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER);
    -                    mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true);
    -                    usleep(mHardwareMixerThread->latency()*1000);
    -                    mHardwareStatus = AUDIO_HW_SET_ROUTING;
    -                    mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER);
    -                    mHardwareStatus = AUDIO_HW_IDLE;
    -                    // delay track start so that audio hardware has time to siwtch routes
    -                    usleep(kStartSleepTime);
    +                if (mForcedRoute == 0) {
    +                    mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC);
    +                    LOGV("++mForcedSpeakerCount == 0, mMusicMuteSaved = %d, mRouteRestoreTime = %d", mMusicMuteSaved, mRouteRestoreTime);
    +                    if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
    +                        LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER);
    +                        mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true);
    +                        usleep(mHardwareMixerThread->latency()*1000);
    +                        mHardwareStatus = AUDIO_HW_SET_ROUTING;
    +                        mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER);
    +                        mHardwareStatus = AUDIO_HW_IDLE;
    +                        // delay track start so that audio hardware has time to siwtch routes
    +                        usleep(kStartSleepTime);
    +                    }
                     }
                     mForcedRoute = AudioSystem::ROUTE_SPEAKER;
    +                mRouteRestoreTime = 0;
                 }
                 LOGV("mForcedSpeakerCount incremented to %d", mForcedSpeakerCount);
             }
    diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
    index 7ae5709792f12..6f7280225bdfa 100644
    --- a/libs/rs/Android.mk
    +++ b/libs/rs/Android.mk
    @@ -94,9 +94,10 @@ LOCAL_SRC_FILES:= \
     	rsType.cpp \
     	rsTriangleMesh.cpp
     
    -LOCAL_SHARED_LIBRARIES += libcutils libutils libEGL libGLESv1_CM libui 
    +LOCAL_SHARED_LIBRARIES += libcutils libutils libEGL libGLESv1_CM libui libacc
     LOCAL_LDLIBS := -lpthread -ldl
     LOCAL_MODULE:= libRS
    +LOCAL_PRELINK_MODULE := false
     
     #LOCAL_MODULE_TAGS := tests
     
    @@ -131,6 +132,7 @@ LOCAL_CFLAGS +=
     LOCAL_LDLIBS := -lpthread
     
     LOCAL_MODULE:= libRS_jni
    +LOCAL_PRELINK_MODULE := false
     
     LOCAL_ADDITIONAL_DEPENDENCIES += $(RS_GENERATED_SOURCES)
     
    diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
    index e1a4b6ded258e..378fcccb35c6f 100644
    --- a/libs/rs/RenderScript.h
    +++ b/libs/rs/RenderScript.h
    @@ -86,6 +86,7 @@ enum RsElementPredefined {
         RS_ELEMENT_USER_I32,
         RS_ELEMENT_USER_FLOAT, 
     
    +    RS_ELEMENT_A_8, 
         RS_ELEMENT_RGB_565, 
         RS_ELEMENT_RGBA_5551, 
         RS_ELEMENT_RGBA_4444, 
    diff --git a/libs/rs/RenderScriptEnv.h b/libs/rs/RenderScriptEnv.h
    index 9ba1a00444c69..dfca56c346795 100644
    --- a/libs/rs/RenderScriptEnv.h
    +++ b/libs/rs/RenderScriptEnv.h
    @@ -58,12 +58,9 @@ typedef struct {
     
         void (*color)(void *con, float r, float g, float b, float a);
     
    -    void (*renderTriangleMesh)(void *con, RsTriangleMesh);
    -    void (*renderTriangleMeshRange)(void *con, RsTriangleMesh, uint32_t start, uint32_t count);
    -
         void (*programFragmentBindTexture)(void *con, RsProgramFragment, uint32_t slot, RsAllocation);
         void (*programFragmentBindSampler)(void *con, RsProgramFragment, uint32_t slot, RsAllocation);
    -    
    +
         void (*materialDiffuse)(void *con, float r, float g, float b, float a);
         void (*materialSpecular)(void *con, float r, float g, float b, float a);
         void (*lightPosition)(void *con, float x, float y, float z, float w);
    @@ -76,11 +73,18 @@ typedef struct {
     
         uint32_t (*rand)(void *con, uint32_t max);
     
    +    void (*contextBindProgramFragment)(void *con, RsProgramFragment pf);
    +    void (*contextBindProgramFragmentStore)(void *con, RsProgramFragmentStore pfs);
    +
    +
    +    // Drawing funcs
    +    void (*renderTriangleMesh)(void *con, RsTriangleMesh);
    +    void (*renderTriangleMeshRange)(void *con, RsTriangleMesh, uint32_t start, uint32_t count);
    +
         // Assumes (GL_FIXED) x,y,z (GL_UNSIGNED_BYTE)r,g,b,a
         void (*drawTriangleArray)(void *con, RsAllocation alloc, uint32_t count);
     
    -    void (*contextBindProgramFragment)(void *con, RsProgramFragment pf);
    -    void (*contextBindProgramFragmentStore)(void *con, RsProgramFragmentStore pfs);
    +    void (*drawRect)(void *con, int32_t x1, int32_t x2, int32_t y1, int32_t y2);
     } rsc_FunctionTable;
     
     typedef void (*rsc_RunScript)(void *con, const rsc_FunctionTable *, uint32_t launchID);
    diff --git a/libs/rs/java/Fountain/AndroidManifest.xml b/libs/rs/java/Fountain/AndroidManifest.xml
    index 62b0b0d1780d3..a10938bae863d 100644
    --- a/libs/rs/java/Fountain/AndroidManifest.xml
    +++ b/libs/rs/java/Fountain/AndroidManifest.xml
    @@ -1,6 +1,6 @@
     
     
    +    package="com.android.fountain">
         
             
    diff --git a/libs/rs/java/Fountain/res/drawable/gadgets_clock_mp3.png b/libs/rs/java/Fountain/res/drawable/gadgets_clock_mp3.png
    new file mode 100755
    index 0000000000000..e91bfb418a8e0
    Binary files /dev/null and b/libs/rs/java/Fountain/res/drawable/gadgets_clock_mp3.png differ
    diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c
    new file mode 100644
    index 0000000000000..76f8dcf10ce14
    --- /dev/null
    +++ b/libs/rs/java/Fountain/res/raw/fountain.c
    @@ -0,0 +1,111 @@
    +// Fountain test script
    +
    +main(con, ft, launchID) {
    +    int count, touch, x, y, rate, maxLife, lifeShift;
    +    int life;
    +    int ct, ct2;
    +    int newPart;
    +    int drawCount;
    +    int dx, dy, idx;
    +    int partPtr;
    +    int vertPtr;
    +    int posx,posy;
    +    int c;
    +
    +    count = loadI32(con, 0, 1);
    +    touch = loadI32(con, 0, 2);
    +    x = loadI32(con, 0, 3);
    +    y = 480 - loadI32(con, 0, 4);
    +
    +    rate = 4;
    +    maxLife = (count / rate) - 1;
    +    lifeShift = 0;
    +    {
    +        life = maxLife;
    +        while (life > 255) {
    +            life = life >> 1;
    +            lifeShift ++;
    +        }
    +    }
    +
    +    contextBindProgramFragment(con, loadI32(con, 0, 7));
    +    drawRect(con, 0, 256, 0, 512);
    +    contextBindProgramFragment(con, loadI32(con, 0, 6));
    +
    +    if (touch) {
    +        newPart = loadI32(con, 2, 0);
    +        for (ct2=0; ct2= count) {
    +                newPart = 0;
    +            }
    +        }
    +        storeI32(con, 2, 0, newPart);
    +    }
    +
    +    // Emulate intrinsic perf...
    +    partPtr = loadVp(con, 2, 4);
    +    vertPtr = loadVp(con, 1, 0);
    +
    +    drawCount = 0;
    +    for (ct=0; ct < count; ct++) {
    +        //int srcIdx = ct * 5 + 1;
    +        //int dstIdx = ct * 3 * 3;
    +
    +        dx = * (int* )(partPtr + 0); //loadEnvI32(con, 2, srcIdx);
    +        dy = * (int* )(partPtr + 4); //loadEnvI32(con, 2, srcIdx + 1);
    +        life = * (int* )(partPtr + 8); //loadEnvI32(con, 2, srcIdx + 2);
    +        posx = * (int* )(partPtr + 12); //loadEnvI32(con, 2, srcIdx + 3);
    +        posy = * (int* )(partPtr + 16); //loadEnvI32(con, 2, srcIdx + 4);
    +
    +        if (life) {
    +            if (posy > 0) {
    +                c = 0xffafcf | ((life >> lifeShift) << 24);
    +
    +                * (int* )(vertPtr) = c; //storeEnvU32(con, 1, dstIdx, c);
    +                * (int* )(vertPtr + 4) = posx; //storeEnvI32(con, 1, dstIdx + 1, posx);
    +                * (int* )(vertPtr + 8) = posy; //storeEnvI32(con, 1, dstIdx + 2, posy);
    +
    +                * (int* )(vertPtr + 12) = c; //storeEnvU32(con, 1, dstIdx + 3, c);
    +                * (int* )(vertPtr + 16) = posx + 0x10000; //storeEnvI32(con, 1, dstIdx + 4, posx + 0x10000);
    +                * (int* )(vertPtr + 20) = posy + dy * 4; //storeEnvI32(con, 1, dstIdx + 5, posy);
    +
    +                * (int* )(vertPtr + 24) = c; //storeEnvU32(con, 1, dstIdx + 6, c);
    +                * (int* )(vertPtr + 28) = posx - 0x10000; //storeEnvI32(con, 1, dstIdx + 7, posx + 0x0800);
    +                * (int* )(vertPtr + 32) = posy + dy * 4; //storeEnvI32(con, 1, dstIdx + 8, posy + 0x10000);
    +
    +                vertPtr = vertPtr + 36;
    +                drawCount ++;
    +            } else {
    +                if (dy < 0) {
    +                    dy = (-dy) >> 1;
    +                }
    +            }
    +
    +            posx = posx + dx;
    +            posy = posy + dy;
    +            dy = dy - 0x400;
    +            life --;
    +
    +            * (int* )(partPtr + 0) = dx; //storeEnvI32(con, 2, srcIdx, dx);
    +            * (int* )(partPtr + 4) = dy; //storeEnvI32(con, 2, srcIdx + 1, dy);
    +            * (int* )(partPtr + 8) = life; //storeEnvI32(con, 2, srcIdx + 2, life);
    +            * (int* )(partPtr + 12) = posx; //storeEnvI32(con, 2, srcIdx + 3, posx);
    +            * (int* )(partPtr + 16) = posy; //storeEnvI32(con, 2, srcIdx + 4, posy);
    +        }
    +
    +        partPtr = partPtr + 20;
    +    }
    +
    +    drawTriangleArray(con, loadI32(con, 0, 5), drawCount);
    +}
    diff --git a/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java b/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java
    index ca0f02003ccc6..0d669660c84b0 100644
    --- a/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java
    +++ b/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java
    @@ -14,7 +14,7 @@
      * limitations under the License.
      */
     
    -package com.android.calc;
    +package com.android.fountain;
     
     import android.app.Activity;
     import android.content.res.Configuration;
    diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
    index b6aa9f8bab1ba..338152598bd75 100644
    --- a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
    +++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
    @@ -14,13 +14,17 @@
      * limitations under the License.
      */
     
    -package com.android.calc;
    +package com.android.fountain;
     
     import java.io.Writer;
     import java.util.ArrayList;
     import java.util.concurrent.Semaphore;
     
     import android.content.Context;
    +import android.content.res.Resources;
    +import android.graphics.Bitmap;
    +import android.graphics.drawable.BitmapDrawable;
    +import android.graphics.drawable.Drawable;
     import android.os.Handler;
     import android.os.Message;
     import android.util.AttributeSet;
    @@ -46,6 +50,11 @@ public class FountainView extends RSSurfaceView {
         private RenderScript.Script mScript;
         private RenderScript.ProgramFragmentStore mPFS;
         private RenderScript.ProgramFragment mPF;
    +    private RenderScript.ProgramFragment mPF2;
    +    private RenderScript.Allocation mTexture;
    +    private RenderScript.Sampler mSampler;
    +
    +    private Bitmap mBackground;
     
         int mParams[] = new int[10];
     
    @@ -58,15 +67,39 @@ public class FountainView extends RSSurfaceView {
             mPartAlloc = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, partCount * 3 * 3);
             mVertAlloc = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, partCount * 5 + 1);
     
    +        {
    +            Resources res = getResources();
    +            Drawable d = res.getDrawable(R.drawable.gadgets_clock_mp3);
    +            BitmapDrawable bd = (BitmapDrawable)d;
    +            Bitmap b = bd.getBitmap();
    +            mTexture = mRS.allocationCreateFromBitmap(b,
    +                                                      RenderScript.ElementPredefined.RGB_565,
    +                                                      true);
    +            mTexture.uploadToTexture(0);
    +        }
    +
             mRS.programFragmentStoreBegin(null, null);
             mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.SRC_ALPHA, RenderScript.BlendDstFunc.ONE);
             mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.ALWAYS);
             mPFS = mRS.programFragmentStoreCreate();
             mRS.contextBindProgramFragmentStore(mPFS);
     
    +        mRS.samplerBegin();
    +        mRS.samplerSet(RenderScript.SamplerParam.FILTER_MAG, RenderScript.SamplerValue.LINEAR);
    +        mRS.samplerSet(RenderScript.SamplerParam.FILTER_MIN, RenderScript.SamplerValue.LINEAR);
    +        mSampler = mRS.samplerCreate();
    +
    +
             mRS.programFragmentBegin(null, null);
             mPF = mRS.programFragmentCreate();
    -        mRS.contextBindProgramFragment(mPF);
    +        //mRS.contextBindProgramFragment(mPF);
    +
    +        mRS.programFragmentBegin(null, null);
    +        mRS.programFragmentSetTexEnable(0, true);
    +        mPF2 = mRS.programFragmentCreate();
    +        mRS.contextBindProgramFragment(mPF2);
    +        mPF2.bindTexture(mTexture, 0);
    +        mPF2.bindSampler(mSampler, 0);
     
             mParams[0] = 0;
             mParams[1] = partCount;
    @@ -74,6 +107,8 @@ public class FountainView extends RSSurfaceView {
             mParams[3] = 0;
             mParams[4] = 0;
             mParams[5] = mPartAlloc.mID;
    +        mParams[6] = mPF.mID;
    +        mParams[7] = mPF2.mID;
             mIntAlloc.data(mParams);
     
             int t2[] = new int[partCount * 4*3];
    @@ -84,7 +119,7 @@ public class FountainView extends RSSurfaceView {
     
             mRS.scriptCBegin();
             mRS.scriptCSetClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    -        mRS.scriptCSetScript("");
    +        mRS.scriptCSetScript(getResources(), R.raw.fountain);
             mRS.scriptCSetRoot(true);
             mScript = mRS.scriptCCreate();
     
    diff --git a/libs/rs/java/Fountain/src/com/android/fountain/RSSurfaceView.java b/libs/rs/java/Fountain/src/com/android/fountain/RSSurfaceView.java
    index d18270a70b191..a8b3bca95f480 100644
    --- a/libs/rs/java/Fountain/src/com/android/fountain/RSSurfaceView.java
    +++ b/libs/rs/java/Fountain/src/com/android/fountain/RSSurfaceView.java
    @@ -14,7 +14,7 @@
      * limitations under the License.
      */
     
    -package com.android.calc;
    +package com.android.fountain;
     
     import java.io.Writer;
     import java.util.ArrayList;
    diff --git a/libs/rs/java/Fountain/src/com/android/fountain/RenderScript.java b/libs/rs/java/Fountain/src/com/android/fountain/RenderScript.java
    index bab966618cffd..cf16cec7c5a5c 100644
    --- a/libs/rs/java/Fountain/src/com/android/fountain/RenderScript.java
    +++ b/libs/rs/java/Fountain/src/com/android/fountain/RenderScript.java
    @@ -14,9 +14,13 @@
      * limitations under the License.
      */
     
    -package com.android.calc;
    +package com.android.fountain;
    +
    +import java.io.InputStream;
    +import java.io.IOException;
     
     import android.os.Bundle;
    +import android.content.res.Resources;
     import android.util.Log;
     import android.util.Config;
     import android.view.Menu;
    @@ -24,6 +28,8 @@ import android.view.MenuItem;
     import android.view.Window;
     import android.view.View;
     import android.view.Surface;
    +import android.graphics.Bitmap;
    +import android.graphics.Color;
     
     public class RenderScript {
         private static final String LOG_TAG = "libRS_jni";
    @@ -32,7 +38,7 @@ public class RenderScript {
     
     
     
    -       /*
    +     /*
          * We use a class initializer to allow the native code to cache some
          * field offsets.
          */
    @@ -43,9 +49,7 @@ public class RenderScript {
             sInitialized = false;
             try {
                 System.loadLibrary("RS_jni");
    -            Log.e(LOG_TAG, "*** Renderscript INIT");
                 _nInit();
    -            Log.e(LOG_TAG, "*** Renderscript INIT 3");
                 sInitialized = true;
             } catch (UnsatisfiedLinkError e) {
                 Log.d(LOG_TAG, "RenderScript JNI library not found!");
    @@ -79,6 +83,8 @@ public class RenderScript {
         native private int  nAllocationCreateTyped(int type);
         native private int  nAllocationCreatePredefSized(int predef, int count);
         native private int  nAllocationCreateSized(int elem, int count);
    +    native private int  nAllocationCreateFromBitmap(int w, int h, int dstFmt, int srcFmt, boolean genMips, int[] data);
    +
         //native private int  nAllocationCreateFromBitmap(type.mID);
         native private void nAllocationUploadToTexture(int alloc, int baseMioLevel);
         native private void nAllocationDestroy(int alloc);
    @@ -115,9 +121,13 @@ public class RenderScript {
         native private void nScriptCSetClearStencil(int stencil);
         native private void nScriptCAddType(int type);
         native private void nScriptCSetRoot(boolean isRoot);
    -    native private void nScriptCSetScript(String s);
    +    native private void nScriptCSetScript(byte[] script, int offset, int length);
         native private int  nScriptCCreate();
     
    +    native private void nSamplerDestroy(int sampler);
    +    native private void nSamplerBegin();
    +    native private void nSamplerSet(int param, int value);
    +    native private int  nSamplerCreate();
     
         native private void nProgramFragmentStoreBegin(int in, int out);
         native private void nProgramFragmentStoreDepthFunc(int func);
    @@ -143,7 +153,7 @@ public class RenderScript {
     
     
         ///////////////////////////////////////////////////////////////////////////////////
    -    // 
    +    //
     
         RenderScript(Surface sur) {
             mSurface = sur;
    @@ -160,14 +170,14 @@ public class RenderScript {
             protected void finalize() throws Throwable
             {
                 if (mID != 0) {
    -                Log.v(LOG_TAG, 
    +                Log.v(LOG_TAG,
                           "Element finalized without having released the RS reference.");
                 }
                 super.finalize();
             }
         }
     
    -    
    +
         //////////////////////////////////////////////////////////////////////////////////
         // Element
     
    @@ -180,20 +190,21 @@ public class RenderScript {
             USER_I32 (5),
             USER_FLOAT (6),
     
    -        RGB_565 (7),
    -        RGBA_5551 (8),
    -        RGBA_4444 (9),
    -        RGB_888 (10),
    -        RGBA_8888 (11),
    +        A_8 (7),
    +        RGB_565 (8),
    +        RGBA_5551 (9),
    +        RGBA_4444 (10),
    +        RGB_888 (11),
    +        RGBA_8888 (12),
     
    -        INDEX_16 (12),
    -        INDEX_32 (13),
    -        XY_F32 (14),
    -        XYZ_F32 (15),
    -        ST_XY_F32 (16),
    -        ST_XYZ_F32 (17),
    -        NORM_XYZ_F32 (18),
    -        NORM_ST_XYZ_F32 (19);
    +        INDEX_16 (13),
    +        INDEX_32 (14),
    +        XY_F32 (15),
    +        XYZ_F32 (16),
    +        ST_XY_F32 (17),
    +        ST_XYZ_F32 (18),
    +        NORM_XYZ_F32 (19),
    +        NORM_ST_XYZ_F32 (20);
     
             int mID;
             ElementPredefined(int id) {
    @@ -298,6 +309,34 @@ public class RenderScript {
             }
         }
     
    +    public enum SamplerParam {
    +        FILTER_MIN (0),
    +        FILTER_MAG (1),
    +        WRAP_MODE_S (2),
    +        WRAP_MODE_T (3),
    +        WRAP_MODE_R (4);
    +
    +        int mID;
    +        SamplerParam(int id) {
    +            mID = id;
    +        }
    +    }
    +
    +    public enum SamplerValue {
    +        NEAREST (0),
    +        LINEAR (1),
    +        LINEAR_MIP_LINEAR (2),
    +        WRAP (3),
    +        CLAMP (4);
    +
    +        int mID;
    +        SamplerValue(int id) {
    +            mID = id;
    +        }
    +    }
    +
    +
    +
         public class Element extends BaseObj {
             Element(int id) {
                 mID = id;
    @@ -435,10 +474,44 @@ public class RenderScript {
             return new Allocation(id);
         }
     
    -    //public Allocation allocationCreateFromBitmap(string file, boolean genMips) {
    -        //int id = nAllocationCreateTyped(type.mID);
    -        //return new Allocation(id);
    -    //}
    +    public Allocation allocationCreateFromBitmap(Bitmap b, ElementPredefined dstFmt, boolean genMips) {
    +        int w = b.getWidth();
    +        int h = b.getHeight();
    +        int[] data = new int[w * h];
    +
    +        int outPtr = 0;
    +        for(int y=0; y < h; y++) {
    +            for(int x=0; x < w; x++) {
    +                data[outPtr] = b.getPixel(x, y);
    +                outPtr++;
    +            }
    +        }
    +
    +        int srcFmt = 0;
    +        /*
    +        switch(b.getConfig()) {
    +        case ALPHA_8:
    +            srcFmt = ElementPredefined.A_8.mID;
    +            break;
    +        case ARGB_4444:
    +            srcFmt = ElementPredefined.RGBA_4444.mID;
    +            break;
    +        case ARGB_8888:
    +            srcFmt = ElementPredefined.RGBA_8888.mID;
    +            break;
    +        case RGB_565:
    +            srcFmt = ElementPredefined.RGB_565.mID;
    +            break;
    +        default:
    +            Log.e(LOG_TAG, "allocationCreateFromBitmap, unknown bitmap format");
    +        }
    +        */
    +
    +        srcFmt = ElementPredefined.RGBA_8888.mID;
    +
    +        int id = nAllocationCreateFromBitmap(w, h, dstFmt.mID, srcFmt, genMips, data);
    +        return new Allocation(id);
    +    }
     
         //////////////////////////////////////////////////////////////////////////////////
         // Adapter1D
    @@ -570,7 +643,45 @@ public class RenderScript {
         }
     
         public void scriptCSetScript(String s) {
    -        nScriptCSetScript(s);
    +        try {
    +            byte[] bytes = s.getBytes("UTF-8");
    +            nScriptCSetScript(bytes, 0, bytes.length);
    +        } catch (java.io.UnsupportedEncodingException e) {
    +            throw new RuntimeException(e);
    +        }
    +    }
    +
    +    public void scriptCSetScript(Resources resources, int id) {
    +        InputStream is = resources.openRawResource(id);
    +        try {
    +            try {
    +                scriptCSetScript(is);
    +            } finally {
    +                is.close();
    +            }
    +        } catch(IOException e) {
    +            throw new Resources.NotFoundException();
    +        }
    +    }
    +
    +    public void  scriptCSetScript(InputStream is) throws IOException {
    +        byte[] buf = new byte[1024];
    +        int currentPos = 0;
    +        while(true) {
    +            int bytesLeft = buf.length - currentPos;
    +            if (bytesLeft == 0) {
    +                byte[] buf2 = new byte[buf.length * 2];
    +                System.arraycopy(buf, 0, buf2, 0, buf.length);
    +                buf = buf2;
    +                bytesLeft = buf.length - currentPos;
    +            }
    +            int bytesRead = is.read(buf, currentPos, bytesLeft);
    +            if (bytesRead <= 0) {
    +                break;
    +            }
    +            currentPos += bytesRead;
    +        }
    +        nScriptCSetScript(buf, 0, currentPos);
         }
     
         public Script scriptCCreate() {
    @@ -646,9 +757,9 @@ public class RenderScript {
                 nProgramFragmentBindTexture(mID, slot, va.mID);
             }
     
    -        //public void bindSampler(Sampler vs, int slot) {
    -            //nProgramFragmentBindSampler(mID, slot, vs.mID);
    -        //}
    +        public void bindSampler(Sampler vs, int slot) {
    +            nProgramFragmentBindSampler(mID, slot, vs.mID);
    +        }
         }
     
         public void programFragmentBegin(Element in, Element out) {
    @@ -680,6 +791,33 @@ public class RenderScript {
             return new ProgramFragment(id);
         }
     
    +    //////////////////////////////////////////////////////////////////////////////////
    +    // Sampler
    +
    +    public class Sampler extends BaseObj {
    +        Sampler(int id) {
    +            mID = id;
    +        }
    +
    +        public void destroy() {
    +            nSamplerDestroy(mID);
    +            mID = 0;
    +        }
    +    }
    +
    +    public void samplerBegin() {
    +        nSamplerBegin();
    +    }
    +
    +    public void samplerSet(SamplerParam p, SamplerValue v) {
    +        nSamplerSet(p.mID, v.mID);
    +    }
    +
    +    public Sampler samplerCreate() {
    +        int id = nSamplerCreate();
    +        return new Sampler(id);
    +    }
    +
     
         ///////////////////////////////////////////////////////////////////////////////////
         // Root state
    diff --git a/libs/rs/jni/RenderScript_jni.cpp b/libs/rs/jni/RenderScript_jni.cpp
    index b3444c0bb31b2..4af58a67d2b6e 100644
    --- a/libs/rs/jni/RenderScript_jni.cpp
    +++ b/libs/rs/jni/RenderScript_jni.cpp
    @@ -33,248 +33,13 @@
     #include "../RenderScript.h"
     #include "../RenderScriptEnv.h"
     
    -#define USE_ACC
    -
    -#ifdef USE_ACC
     #include "acc/acc.h"
    -#endif
     
     //#define LOG_API LOGE
     #define LOG_API(...)
     
     using namespace android;
     
    -extern "C" void test_script(void *con, const rsc_FunctionTable *ft, uint32_t launchID);
    -
    -#ifdef USE_ACC
    -static const char* TEST_SCRIPT = ""
    -        "// Fountain test script\n"
    -        "\n"
    -        "main(con, ft, launchID) {\n"
    -        "    int count, touch, x, y, rate, maxLife, lifeShift;\n"
    -        "    int life;\n"
    -        "    int ct, ct2;\n"
    -        "    int newPart;\n"
    -        "    int drawCount;\n"
    -        "    int dx, dy, idx;\n"
    -        "    int partPtr;\n"
    -        "    int vertPtr;\n"
    -        "    int posx,posy;\n"
    -        "    int c;\n"
    -        "\n"
    -        "    count = loadI32(con, 0, 1);\n"
    -        "    touch = loadI32(con, 0, 2);\n"
    -        "    x = loadI32(con, 0, 3);\n"
    -        "    y = 480 - loadI32(con, 0, 4);\n"
    -        "\n"
    -        "    rate = 4;\n"
    -        "    maxLife = (count / rate) - 1;\n"
    -        "    lifeShift = 0;\n"
    -        "    {\n"
    -        "        life = maxLife;\n"
    -        "        while (life > 255) {\n"
    -        "            life = life >> 1;\n"
    -        "            lifeShift ++;\n"
    -        "        }\n"
    -        "    }\n"
    -        "\n"
    -        "    if (touch) {\n"
    -        "        newPart = loadI32(con, 2, 0);\n"
    -        "        for (ct2=0; ct2= count) {\n"
    -        "                newPart = 0;\n"
    -        "            }\n"
    -        "        }\n"
    -        "        storeI32(con, 2, 0, newPart);\n"
    -        "    }\n"
    -        "\n"
    -        "    // Emulate intrinsic perf...\n"
    -        "    partPtr = loadVp(con, 2, 4);\n"
    -        "    vertPtr = loadVp(con, 1, 0);\n"
    -        "\n"
    -        "    drawCount = 0;\n"
    -        "    for (ct=0; ct < count; ct++) {\n"
    -        "        //int srcIdx = ct * 5 + 1;\n"
    -        "        //int dstIdx = ct * 3 * 3;\n"
    -        "\n"
    -        "        dx = * (int* )(partPtr + 0); //loadEnvI32(con, 2, srcIdx);\n"
    -        "        dy = * (int* )(partPtr + 4); //loadEnvI32(con, 2, srcIdx + 1);\n"
    -        "        life = * (int* )(partPtr + 8); //loadEnvI32(con, 2, srcIdx + 2);\n"
    -        "        posx = * (int* )(partPtr + 12); //loadEnvI32(con, 2, srcIdx + 3);\n"
    -        "        posy = * (int* )(partPtr + 16); //loadEnvI32(con, 2, srcIdx + 4);\n"
    -        "\n"
    -        "        if (life) {\n"
    -        "            if (posy > 0) {\n"
    -        "                c = 0xffafcf | ((life >> lifeShift) << 24);\n"
    -        "\n"
    -        "                * (int* )(vertPtr) = c; //storeEnvU32(con, 1, dstIdx, c);\n"
    -        "                * (int* )(vertPtr + 4) = posx; //storeEnvI32(con, 1, dstIdx + 1, posx);\n"
    -        "                * (int* )(vertPtr + 8) = posy; //storeEnvI32(con, 1, dstIdx + 2, posy);\n"
    -        "\n"
    -        "                * (int* )(vertPtr + 12) = c; //storeEnvU32(con, 1, dstIdx + 3, c);\n"
    -        "                * (int* )(vertPtr + 16) = posx + 0x10000; //storeEnvI32(con, 1, dstIdx + 4, posx + 0x10000);\n"
    -        "                * (int* )(vertPtr + 20) = posy + dy * 4; //storeEnvI32(con, 1, dstIdx + 5, posy);\n"
    -        "\n"
    -        "                * (int* )(vertPtr + 24) = c; //storeEnvU32(con, 1, dstIdx + 6, c);\n"
    -        "                * (int* )(vertPtr + 28) = posx - 0x10000; //storeEnvI32(con, 1, dstIdx + 7, posx + 0x0800);\n"
    -        "                * (int* )(vertPtr + 32) = posy + dy * 4; //storeEnvI32(con, 1, dstIdx + 8, posy + 0x10000);\n"
    -        "\n"
    -        "                vertPtr = vertPtr + 36;\n"
    -        "                drawCount ++;\n"
    -        "            } else {\n"
    -        "                if (dy < 0) {\n"
    -        "                    dy = (-dy) >> 1;\n"
    -        "                }\n"
    -        "            }\n"
    -        "\n"
    -        "            posx = posx + dx;\n"
    -        "            posy = posy + dy;\n"
    -        "            dy = dy - 0x400;\n"
    -        "            life --;\n"
    -        "\n"
    -        "            * (int* )(partPtr + 0) = dx; //storeEnvI32(con, 2, srcIdx, dx);\n"
    -        "            * (int* )(partPtr + 4) = dy; //storeEnvI32(con, 2, srcIdx + 1, dy);\n"
    -        "            * (int* )(partPtr + 8) = life; //storeEnvI32(con, 2, srcIdx + 2, life);\n"
    -        "            * (int* )(partPtr + 12) = posx; //storeEnvI32(con, 2, srcIdx + 3, posx);\n"
    -        "            * (int* )(partPtr + 16) = posy; //storeEnvI32(con, 2, srcIdx + 4, posy);\n"
    -        "        }\n"
    -        "\n"
    -        "        partPtr = partPtr + 20;\n"
    -        "    }\n"
    -        "\n"
    -        "    drawTriangleArray(con, loadI32(con, 0, 5), drawCount);\n"
    -        "}\n";
    -
    -typedef void (*ScriptEntry)(void *con, const rsc_FunctionTable *ft, uint32_t launchID);
    -
    -ACCscript* gScript;
    -ScriptEntry gScriptEntry;
    -
    -void test_script(void *con, const rsc_FunctionTable *ft, uint32_t launchID)
    -{
    -    if (!gScript) {
    -        gScript = accCreateScript();
    -        const char* scriptSource[] = { TEST_SCRIPT };
    -        accScriptSource(gScript, 1, scriptSource, NULL);
    -        accCompileScript(gScript);
    -        accGetScriptLabel(gScript, "main", (ACCvoid**) &gScriptEntry);
    -    }
    -    if (gScriptEntry) {
    -        gScriptEntry(con, ft, launchID);
    -    }
    -}
    -
    -
    -#else
    -void test_script(void *con, const rsc_FunctionTable *ft, uint32_t launchID)
    -{
    -    int count = ft->loadEnvI32(con, 0, 1);
    -    int touch = ft->loadEnvI32(con, 0, 2);
    -    int x = ft->loadEnvI32(con, 0, 3);
    -    int y = 480 - ft->loadEnvI32(con, 0, 4);
    -
    -    int rate = 4;
    -    int maxLife = (count / rate) - 1;
    -    int lifeShift = 0;
    -    {
    -        int life = maxLife;
    -        while (life > 255) {
    -            life >>= 1;
    -            lifeShift ++;
    -        }
    -    }
    -
    -    if (touch) {
    -        int newPart = ft->loadEnvI32(con, 2, 0);
    -        for (int ct2=0; ct2rand(con, 0x10000) - 0x8000;
    -            int dy = ft->rand(con, 0x10000) - 0x8000;
    -
    -            int idx = newPart * 5 + 1;
    -            ft->storeEnvI32(con, 2, idx, dx);
    -            ft->storeEnvI32(con, 2, idx + 1, dy);
    -            ft->storeEnvI32(con, 2, idx + 2, maxLife);
    -            ft->storeEnvI32(con, 2, idx + 3, x << 16);
    -            ft->storeEnvI32(con, 2, idx + 4, y << 16);
    -
    -            newPart++;
    -            if (newPart >= count) {
    -                newPart = 0;
    -            }
    -        }
    -        ft->storeEnvI32(con, 2, 0, newPart);
    -    }
    -
    -    // Emulate intrinsic perf...
    -    int32_t * partPtr = (int32_t *)ft->loadEnvVp(con, 2, 4);
    -    int32_t * vertPtr = (int32_t *)ft->loadEnvVp(con, 1, 0);
    -
    -    int drawCount = 0;
    -    for (int ct=0; ct < count; ct++) {
    -        //int srcIdx = ct * 5 + 1;
    -        //int dstIdx = ct * 3 * 3;
    -
    -        int dx = partPtr[0]; //ft->loadEnvI32(con, 2, srcIdx);
    -        int dy = partPtr[1]; //ft->loadEnvI32(con, 2, srcIdx + 1);
    -        int life = partPtr[2]; //ft->loadEnvI32(con, 2, srcIdx + 2);
    -        int posx = partPtr[3]; //ft->loadEnvI32(con, 2, srcIdx + 3);
    -        int posy = partPtr[4]; //ft->loadEnvI32(con, 2, srcIdx + 4);
    -
    -        if (life) {
    -            if (posy > 0) {
    -                uint32_t c = 0xffafcf | ((life >> lifeShift) << 24);
    -
    -                ((uint32_t *)vertPtr)[0] = c; //ft->storeEnvU32(con, 1, dstIdx, c);
    -                vertPtr[1] = posx; //ft->storeEnvI32(con, 1, dstIdx + 1, posx);
    -                vertPtr[2] = posy; //ft->storeEnvI32(con, 1, dstIdx + 2, posy);
    -
    -                ((uint32_t *)vertPtr)[3] = c; //ft->storeEnvU32(con, 1, dstIdx + 3, c);
    -                vertPtr[4] = posx + 0x10000; //ft->storeEnvI32(con, 1, dstIdx + 4, posx + 0x10000);
    -                vertPtr[5] = posy + dy * 4; //ft->storeEnvI32(con, 1, dstIdx + 5, posy);
    -
    -                ((uint32_t *)vertPtr)[6] = c; //ft->storeEnvU32(con, 1, dstIdx + 6, c);
    -                vertPtr[7] = posx - 0x10000; //ft->storeEnvI32(con, 1, dstIdx + 7, posx + 0x0800);
    -                vertPtr[8] = posy + dy * 4; //ft->storeEnvI32(con, 1, dstIdx + 8, posy + 0x10000);
    -
    -                vertPtr += 9;
    -                drawCount ++;
    -            } else {
    -                if (dy < 0) {
    -                    dy = (-dy) >> 1;
    -                }
    -            }
    -
    -            posx += dx;
    -            posy += dy;
    -            dy -= 0x400;
    -            life --;
    -
    -            partPtr[0] = dx; //ft->storeEnvI32(con, 2, srcIdx, dx);
    -            partPtr[1] = dy; //ft->storeEnvI32(con, 2, srcIdx + 1, dy);
    -            partPtr[2] = life; //ft->storeEnvI32(con, 2, srcIdx + 2, life);
    -            partPtr[3] = posx; //ft->storeEnvI32(con, 2, srcIdx + 3, posx);
    -            partPtr[4] = posy; //ft->storeEnvI32(con, 2, srcIdx + 4, posy);
    -        }
    -
    -        partPtr += 5;
    -    }
    -
    -    ft->drawTriangleArray(con, (RsAllocation)ft->loadEnvI32(con, 0, 5), drawCount);
    -}
    -
    -#endif
    -
     // ---------------------------------------------------------------------------
     
     static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
    @@ -453,6 +218,21 @@ nAllocationUploadToTexture(JNIEnv *_env, jobject _this, jint a, jint mip)
         rsAllocationUploadToTexture((RsAllocation)a, mip);
     }
     
    +static int
    +nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jint w, jint h, jint dstFmt, jint srcFmt, jboolean genMips, jintArray data)
    +{
    +    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
    +    jint len = _env->GetArrayLength(data);
    +    LOG_API("nAllocationCreateFromBitmap, con(%p), w(%i), h(%i), dstFmt(%i), srcFmt(%i), mip(%i), len(%i)", con, w, h, dstFmt, srcFmt, genMips, len);
    +
    +    jint *ptr = _env->GetIntArrayElements(data, NULL);
    +    jint id = (jint)rsAllocationCreateFromBitmap(w, h, (RsElementPredefined)dstFmt, (RsElementPredefined)srcFmt, genMips, ptr);
    +    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
    +    return id;
    +}
    +
    +
    +
     static void
     nAllocationDestroy(JNIEnv *_env, jobject _this, jint a)
     {
    @@ -744,12 +524,62 @@ nScriptCSetRoot(JNIEnv *_env, jobject _this, jboolean isRoot)
     }
     
     static void
    -nScriptCSetScript(JNIEnv *_env, jobject _this, jboolean isRoot)
    +nScriptCSetScript(JNIEnv *_env, jobject _this, jbyteArray scriptRef,
    +                  jint offset, jint length)
     {
         RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
         LOG_API("!!! nScriptCSetScript, con(%p)", con);
    -    //nScriptCSetScript(isRoot);
    -    rsScriptCSetScript((void *)test_script);
    +    jint _exception = 0;
    +    jint remaining;
    +    jbyte* script_base = 0;
    +    jbyte* script_ptr;
    +    ACCscript* script = 0;
    +    void* scriptEntry = 0;
    +    if (!scriptRef) {
    +        _exception = 1;
    +        //_env->ThrowNew(IAEClass, "script == null");
    +        goto exit;
    +    }
    +    if (offset < 0) {
    +        _exception = 1;
    +        //_env->ThrowNew(IAEClass, "offset < 0");
    +        goto exit;
    +    }
    +    if (length < 0) {
    +        _exception = 1;
    +        //_env->ThrowNew(IAEClass, "length < 0");
    +        goto exit;
    +    }
    +    remaining = _env->GetArrayLength(scriptRef) - offset;
    +    if (remaining < length) {
    +        _exception = 1;
    +        //_env->ThrowNew(IAEClass, "length > script.length - offset");
    +        goto exit;
    +    }
    +    script_base = (jbyte *)
    +        _env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0);
    +    script_ptr = script_base + offset;
    +
    +    {
    +        script = accCreateScript();
    +        const char* scriptSource[] = {(const char*) script_ptr};
    +        int scriptLength[] = {length} ;
    +        accScriptSource(script, 1, scriptSource, scriptLength);
    +        accCompileScript(script);
    +        accGetScriptLabel(script, "main", (ACCvoid**) &scriptEntry);
    +    }
    +    if (scriptEntry) {
    +        rsScriptCSetScript((void*) script, (void *)scriptEntry);
    +        script = 0;
    +    }
    +exit:
    +    if (script) {
    +        accDeleteScript(script);
    +    }
    +    if (script_base) {
    +        _env->ReleasePrimitiveArrayCritical(scriptRef, script_base,
    +                _exception ? JNI_ABORT: 0);
    +    }
     }
     
     static jint
    @@ -887,14 +717,6 @@ nContextBindRootScript(JNIEnv *_env, jobject _this, jint script)
         rsContextBindRootScript((RsScript)script);
     }
     
    -static void
    -nContextBindSampler(JNIEnv *_env, jobject _this, jint sampler, jint slot)
    -{
    -    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
    -    LOG_API("nContextBindSampler, con(%p), sampler(%p), slot(%i)", con, (RsSampler)sampler, slot);
    -    rsContextBindSampler(slot, (RsSampler)sampler);
    -}
    -
     static void
     nContextBindProgramFragmentStore(JNIEnv *_env, jobject _this, jint pfs)
     {
    @@ -911,11 +733,45 @@ nContextBindProgramFragment(JNIEnv *_env, jobject _this, jint pf)
         rsContextBindProgramFragment((RsProgramFragment)pf);
     }
     
    +// ---------------------------------------------------------------------------
    +
    +static void
    +nSamplerDestroy(JNIEnv *_env, jobject _this, jint s)
    +{
    +    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
    +    LOG_API("nSamplerDestroy, con(%p), sampler(%p)", con, (RsSampler)s);
    +    rsSamplerDestroy((RsSampler)s);
    +}
    +
    +static void
    +nSamplerBegin(JNIEnv *_env, jobject _this)
    +{
    +    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
    +    LOG_API("nSamplerBegin, con(%p)", con);
    +    rsSamplerBegin();
    +}
    +
    +static void
    +nSamplerSet(JNIEnv *_env, jobject _this, jint p, jint v)
    +{
    +    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
    +    LOG_API("nSamplerSet, con(%p), param(%i), value(%i)", con, p, v);
    +    rsSamplerSet((RsSamplerParam)p, (RsSamplerValue)v);
    +}
    +
    +static jint
    +nSamplerCreate(JNIEnv *_env, jobject _this)
    +{
    +    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
    +    LOG_API("nSamplerCreate, con(%p), script(%p)", con, (RsScript)script);
    +    return (jint)rsSamplerCreate();
    +}
    +
     
     // ---------------------------------------------------------------------------
     
     
    -static const char *classPathName = "com/android/calc/RenderScript";
    +static const char *classPathName = "com/android/fountain/RenderScript";
     
     static JNINativeMethod methods[] = {
     {"_nInit",                         "()V",                                  (void*)_nInit },
    @@ -939,7 +795,7 @@ static JNINativeMethod methods[] = {
     {"nAllocationCreateTyped",         "(I)I",                                 (void*)nAllocationCreateTyped },
     {"nAllocationCreatePredefSized",   "(II)I",                                (void*)nAllocationCreatePredefSized },
     {"nAllocationCreateSized",         "(II)I",                                (void*)nAllocationCreateSized },
    -//{"nAllocationCreateFromBitmap",    "(I)V",                                 (void*)nAllocationCreateFromBitmap },
    +{"nAllocationCreateFromBitmap",    "(IIIIZ[I)I",                           (void*)nAllocationCreateFromBitmap },
     {"nAllocationUploadToTexture",     "(II)V",                                (void*)nAllocationUploadToTexture },
     {"nAllocationDestroy",             "(I)V",                                 (void*)nAllocationDestroy },
     {"nAllocationData",                "(I[I)V",                               (void*)nAllocationData_i },
    @@ -975,7 +831,7 @@ static JNINativeMethod methods[] = {
     {"nScriptCSetClearStencil",        "(I)V",                                 (void*)nScriptCSetClearStencil },
     {"nScriptCAddType",                "(I)V",                                 (void*)nScriptCAddType },
     {"nScriptCSetRoot",                "(Z)V",                                 (void*)nScriptCSetRoot },
    -{"nScriptCSetScript",              "(Ljava/lang/String;)V",                (void*)nScriptCSetScript },
    +{"nScriptCSetScript",              "([BII)V",                              (void*)nScriptCSetScript },
     {"nScriptCCreate",                 "()I",                                  (void*)nScriptCCreate },
     
     {"nProgramFragmentStoreBegin",     "(II)V",                                (void*)nProgramFragmentStoreBegin },
    @@ -995,10 +851,14 @@ static JNINativeMethod methods[] = {
     {"nProgramFragmentCreate",         "()I",                                  (void*)nProgramFragmentCreate },
     
     {"nContextBindRootScript",         "(I)V",                                 (void*)nContextBindRootScript },
    -//{"nContextBindSampler",          "(II)V",                                (void*)nContextBindSampler },
     {"nContextBindProgramFragmentStore","(I)V",                                (void*)nContextBindProgramFragmentStore },
     {"nContextBindProgramFragment",    "(I)V",                                 (void*)nContextBindProgramFragment },
     
    +{"nSamplerDestroy",                "(I)V",                                 (void*)nSamplerDestroy },
    +{"nSamplerBegin",                  "()V",                                  (void*)nSamplerBegin },
    +{"nSamplerSet",                    "(II)V",                                (void*)nSamplerSet },
    +{"nSamplerCreate",                 "()I",                                  (void*)nSamplerCreate },
    +
     };
     
     static int registerFuncs(JNIEnv *_env)
    diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
    index 6168bd75fab57..090be3219c22e 100644
    --- a/libs/rs/rs.spec
    +++ b/libs/rs/rs.spec
    @@ -1,10 +1,5 @@
     
     
    -ContextBindSampler {
    -	param uint32_t slot
    -	param RsSampler sampler
    -	}
    -
     ContextBindRootScript {
     	param RsScript sampler
     	}
    @@ -83,12 +78,23 @@ AllocationCreateSized {
     	ret RsAllocation
     	}
     
    -AllocationCreateFromBitmap {
    +AllocationCreateFromFile {
     	param const char *file
     	param bool genMips
     	ret RsAllocation
     	}
     
    +AllocationCreateFromBitmap {
    +	param uint32_t width
    +	param uint32_t height
    +	param RsElementPredefined dstFmt
    +	param RsElementPredefined srcFmt
    +	param bool genMips
    +	param const void * data
    +	ret RsAllocation
    +	}
    +
    +
     AllocationUploadToTexture {
     	param RsAllocation alloc
     	param uint32_t baseMipLevel
    @@ -201,6 +207,9 @@ SamplerCreate {
     	ret RsSampler
     	}
     
    +SamplerDestroy {
    +	param RsSampler s
    +	}
     
     TriangleMeshBegin {
     	param RsElement vertex
    @@ -277,7 +286,8 @@ ScriptCSetOrtho {
     	}
     
     ScriptCSetScript {
    -	param void * ptr
    +	param void * accScript
    +	param void * codePtr
     	}
     
     ScriptCCreate {
    diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
    index f3f2e4643bf93..7b8bc8034ff2d 100644
    --- a/libs/rs/rsAllocation.cpp
    +++ b/libs/rs/rsAllocation.cpp
    @@ -213,7 +213,104 @@ static void mip(const Adapter2D &out, const Adapter2D &in)
     }
     
     
    -RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, const char *file, bool genMips)
    +typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count);
    +
    +static void elementConverter_cpy_16(void *dst, const void *src, uint32_t count)
    +{
    +    memcpy(dst, src, count * 2);
    +}
    +static void elementConverter_cpy_8(void *dst, const void *src, uint32_t count)
    +{
    +    memcpy(dst, src, count);
    +}
    +static void elementConverter_cpy_32(void *dst, const void *src, uint32_t count)
    +{
    +    memcpy(dst, src, count * 4);
    +}
    +
    +
    +static void elementConverter_888_to_565(void *dst, const void *src, uint32_t count)
    +{
    +    uint16_t *d = static_cast(dst);
    +    const uint8_t *s = static_cast(src);
    +
    +    while(count--) {
    +        *d = rs888to565(s[0], s[1], s[2]);
    +        d++;
    +        s+= 3;
    +    }
    +}
    +
    +static void elementConverter_8888_to_565(void *dst, const void *src, uint32_t count)
    +{
    +    uint16_t *d = static_cast(dst);
    +    const uint8_t *s = static_cast(src);
    +
    +    while(count--) {
    +        *d = rs888to565(s[0], s[1], s[2]);
    +        d++;
    +        s+= 4;
    +    }
    +}
    +
    +static ElementConverter_t pickConverter(RsElementPredefined dstFmt, RsElementPredefined srcFmt)
    +{
    +    if ((dstFmt == RS_ELEMENT_RGB_565) && 
    +        (srcFmt == RS_ELEMENT_RGB_565)) {
    +        return elementConverter_cpy_16;
    +    }
    +
    +    if ((dstFmt == RS_ELEMENT_RGB_565) && 
    +        (srcFmt == RS_ELEMENT_RGB_888)) {
    +        return elementConverter_888_to_565;
    +    }
    +
    +    if ((dstFmt == RS_ELEMENT_RGB_565) && 
    +        (srcFmt == RS_ELEMENT_RGBA_8888)) {
    +        return elementConverter_8888_to_565;
    +    }
    +
    +
    +    LOGE("pickConverter, unsuported combo");
    +    return 0;
    +}
    +
    +
    +RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElementPredefined dstFmt, RsElementPredefined srcFmt,  bool genMips, const void *data)
    +{
    +    rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, RS_ELEMENT_RGB_565));
    +    rsi_TypeAdd(rsc, RS_DIMENSION_X, w);
    +    rsi_TypeAdd(rsc, RS_DIMENSION_Y, h);
    +    if (genMips) {
    +        rsi_TypeAdd(rsc, RS_DIMENSION_LOD, 1);
    +    }
    +    RsType type = rsi_TypeCreate(rsc);
    +
    +    RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type);
    +    Allocation *texAlloc = static_cast(vTexAlloc);
    +    if (texAlloc == NULL) {
    +        LOGE("Memory allocation failure");
    +        return NULL;
    +    }
    +    texAlloc->incRef();
    +
    +    ElementConverter_t cvt = pickConverter(dstFmt, srcFmt);
    +    cvt(texAlloc->getPtr(), data, w * h);
    +
    +    if (genMips) {
    +        Adapter2D adapt(texAlloc);
    +        Adapter2D adapt2(texAlloc);
    +        for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
    +            adapt.setLOD(lod);
    +            adapt2.setLOD(lod + 1);
    +            mip(adapt2, adapt);
    +        }
    +    }
    +
    +    return texAlloc;
    +}
    +
    +RsAllocation rsi_AllocationCreateFromFile(Context *rsc, const char *file, bool genMips)
     {
         typedef struct _Win3xBitmapHeader
         {
    diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
    index 163cf4df8c40e..abc5f456f8eaa 100644
    --- a/libs/rs/rsContext.cpp
    +++ b/libs/rs/rsContext.cpp
    @@ -74,7 +74,7 @@ void Context::runRootScript()
         if(mRootScript->mIsOrtho) {
             glMatrixMode(GL_PROJECTION);
             glLoadIdentity();
    -        glOrthof(0, 320,  0, 480,  0, 1);
    +        glOrthof(0, 320,  480, 0,  0, 1);
             glMatrixMode(GL_MODELVIEW);
         } else {
             glMatrixMode(GL_PROJECTION);
    diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
    index 16375440cb1d9..bd11f725d535a 100644
    --- a/libs/rs/rsElement.cpp
    +++ b/libs/rs/rsElement.cpp
    @@ -91,6 +91,10 @@ void ElementState::initPredefined()
         e->setComponent(0, f_32);
         mPredefinedList.add(Predefined(RS_ELEMENT_USER_FLOAT, e));
     
    +    e = new Element(1);
    +    e->setComponent(0, a_8);
    +    mPredefinedList.add(Predefined(RS_ELEMENT_A_8, e));
    +
         e = new Element(3);
         e->setComponent(0, r_5);
         e->setComponent(1, g_6);
    diff --git a/libs/rs/rsMatrix.cpp b/libs/rs/rsMatrix.cpp
    index 7d22ae0095812..e68d5ac504395 100644
    --- a/libs/rs/rsMatrix.cpp
    +++ b/libs/rs/rsMatrix.cpp
    @@ -17,6 +17,7 @@
     #include "rsMatrix.h"
     
     #include "stdlib.h"
    +#include "string.h"
     #include "math.h"
     
     #include 
    diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
    index 5367c534d01ec..3d316ea1cbda9 100644
    --- a/libs/rs/rsProgramFragment.cpp
    +++ b/libs/rs/rsProgramFragment.cpp
    @@ -40,7 +40,7 @@ void ProgramFragment::setupGL()
         for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
             glActiveTexture(GL_TEXTURE0 + ct);
             if (!(mTextureEnableMask & (1 << ct)) ||
    -            !mSamplers[ct].get() ||
    +            //!mSamplers[ct].get() ||
                 !mTextures[ct].get()) {
     
                 glDisable(GL_TEXTURE_2D);
    @@ -62,7 +62,14 @@ void ProgramFragment::setupGL()
                 break;
             }
     
    -        mSamplers[ct]->setupGL();
    +        if (mSamplers[ct].get()) {
    +            mSamplers[ct]->setupGL();
    +        } else {
    +            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    +            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    +            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    +            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    +        }
         }
         glActiveTexture(GL_TEXTURE0);
     }
    diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp
    index 3c008c9de8cc4..d89346e16cc98 100644
    --- a/libs/rs/rsSampler.cpp
    +++ b/libs/rs/rsSampler.cpp
    @@ -53,11 +53,20 @@ Sampler::~Sampler()
     
     void Sampler::setupGL()
     {
    -    //LOGE("setup gl");
    -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    +    GLenum trans[] = {
    +        GL_NEAREST, //RS_SAMPLER_NEAREST,
    +        GL_LINEAR, //RS_SAMPLER_LINEAR,
    +        GL_LINEAR_MIPMAP_LINEAR, //RS_SAMPLER_LINEAR_MIP_LINEAR,
    +        GL_REPEAT, //RS_SAMPLER_WRAP,
    +        GL_CLAMP_TO_EDGE, //RS_SAMPLER_CLAMP
    +
    +    };
    +
    +
    +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
    +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, trans[mMagFilter]);
    +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, trans[mWrapS]);
    +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, trans[mWrapT]);
     
     }
     
    @@ -76,7 +85,7 @@ void Sampler::unbindFromContext(SamplerState *ss)
     
     void SamplerState::setupGL()
     {
    -    for (uint32_t ct=0; ct < 1/*RS_MAX_SAMPLER_SLOT*/; ct++) {
    +    for (uint32_t ct=0; ct < RS_MAX_SAMPLER_SLOT; ct++) {
             Sampler *s = mSamplers[ct].get();
             if (s) {
                 s->setupGL();
    @@ -140,4 +149,12 @@ RsSampler rsi_SamplerCreate(Context *rsc)
         return s;
     }
     
    +void rsi_SamplerDestroy(Context *rsc, RsSampler vs)
    +{
    +    Sampler * s = static_cast(vs);
    +    s->decRef();
    +
    +}
    +
    +
     }}
    diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
    index 3c4bfa2a59355..2c7d88415f5c5 100644
    --- a/libs/rs/rsScriptC.cpp
    +++ b/libs/rs/rsScriptC.cpp
    @@ -18,17 +18,23 @@
     #include "rsScriptC.h"
     #include "rsMatrix.h"
     
    +#include "acc/acc.h"
    +
     using namespace android;
     using namespace android::renderscript;
     
     
     ScriptC::ScriptC()
     {
    +    mAccScript = NULL;
         mScript = NULL;
     }
     
     ScriptC::~ScriptC()
     {
    +    if (mAccScript) {
    +        accDeleteScript(mAccScript);
    +    }
     }
     
     extern "C" void matrixLoadIdentity(void *con, rsc_Matrix *mat)
    @@ -261,6 +267,35 @@ extern "C" void drawTriangleArray(void *vp, RsAllocation alloc, uint32_t count)
         glDrawArrays(GL_TRIANGLES, 0, count * 3);
     }
     
    +extern "C" void drawRect(void *vp, int32_t x1, int32_t x2, int32_t y1, int32_t y2)
    +{
    +    x1 = (x1 << 16);
    +    x2 = (x2 << 16);
    +    y1 = (y1 << 16);
    +    y2 = (y2 << 16);
    +
    +    int32_t vtx[] = {x1,y1, x1,y2, x2,y1, x2,y2};
    +    static const int32_t tex[] = {0,0, 0,0x10000, 0x10000,0, 0x10000,0x10000};
    +
    +
    +    ScriptC::Env * env = static_cast(vp);
    +    env->mContext->setupCheck();
    +
    +    glBindBuffer(GL_ARRAY_BUFFER, 0);
    +    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
    +
    +    glEnableClientState(GL_VERTEX_ARRAY);
    +    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    +    glDisableClientState(GL_NORMAL_ARRAY);
    +    glDisableClientState(GL_COLOR_ARRAY);
    +
    +    glVertexPointer(2, GL_FIXED, 8, vtx);
    +    glTexCoordPointer(2, GL_FIXED, 8, tex);
    +    //glColorPointer(4, GL_UNSIGNED_BYTE, 12, ptr);
    +
    +    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    +}
    +
     extern "C" void pfBindTexture(void *vp, RsProgramFragment vpf, uint32_t slot, RsAllocation va)
     {
         //LOGE("pfBindTexture %p", vpf);
    @@ -326,8 +361,6 @@ static rsc_FunctionTable scriptCPtrTable = {
         matrixTranslate,
     
         color,
    -    renderTriangleMesh,
    -    renderTriangleMeshRange,
     
         pfBindTexture,
         pfBindSampler,
    @@ -341,9 +374,16 @@ static rsc_FunctionTable scriptCPtrTable = {
         disable,
     
         scriptRand,
    -    drawTriangleArray,
         contextBindProgramFragment,
    -    contextBindProgramFragmentStore
    +    contextBindProgramFragmentStore,
    +
    +
    +    renderTriangleMesh,
    +    renderTriangleMeshRange,
    +
    +    drawTriangleArray,
    +    drawRect
    +
     };
     
     
    @@ -360,6 +400,9 @@ ScriptCState::ScriptCState()
     
     ScriptCState::~ScriptCState()
     {
    +    if (mAccScript) {
    +        accDeleteScript(mAccScript);
    +    }
     }
     
     void ScriptCState::clear()
    @@ -371,6 +414,7 @@ void ScriptCState::clear()
         mClearColor[3] = 1;
         mClearDepth = 1;
         mClearStencil = 0;
    +    mAccScript = NULL;
         mScript = NULL;
         mIsRoot = false;
         mIsOrtho = true;
    @@ -412,9 +456,10 @@ void rsi_ScriptCAddType(Context * rsc, RsType vt)
         ss->mConstantBufferTypes.add(static_cast(vt));
     }
     
    -void rsi_ScriptCSetScript(Context * rsc, void *vp)
    +void rsi_ScriptCSetScript(Context * rsc, void* accScript, void *vp)
     {
         ScriptCState *ss = &rsc->mScriptC;
    +    ss->mAccScript = reinterpret_cast(accScript);
         ss->mScript = reinterpret_cast(vp);
     }
     
    @@ -435,6 +480,8 @@ RsScript rsi_ScriptCCreate(Context * rsc)
         ScriptCState *ss = &rsc->mScriptC;
     
         ScriptC *s = new ScriptC();
    +    s->mAccScript = ss->mAccScript;
    +    ss->mAccScript = NULL;
         s->mScript = ss->mScript;
         s->mClearColor[0] = ss->mClearColor[0];
         s->mClearColor[1] = ss->mClearColor[1];
    diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
    index f35a130767cac..c58dcf9d4b1ba 100644
    --- a/libs/rs/rsScriptC.h
    +++ b/libs/rs/rsScriptC.h
    @@ -21,11 +21,13 @@
     
     #include "RenderScriptEnv.h"
     
    +struct ACCscript;
    +
     // ---------------------------------------------------------------------------
     namespace android {
     namespace renderscript {
     
    -    
    +
     
     class ScriptC : public Script
     {
    @@ -38,6 +40,7 @@ public:
         virtual void run(Context *, uint32_t launchID);
     
     
    +    ACCscript*    mAccScript;
         rsc_RunScript mScript;
     
     
    @@ -48,13 +51,13 @@ public:
     
     };
     
    -class ScriptCState 
    +class ScriptCState
     {
     public:
         ScriptCState();
         ~ScriptCState();
     
    -
    +    ACCscript*    mAccScript;
         rsc_RunScript mScript;
         float mClearColor[4];
         float mClearDepth;
    diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
    index 30b6733decbe0..afad48e67f6bc 100644
    --- a/libs/utils/Android.mk
    +++ b/libs/utils/Android.mk
    @@ -55,7 +55,6 @@ commonSources:= \
     #
     hostSources:= \
     	InetAddress.cpp \
    -	Pipe.cpp \
     	Socket.cpp \
     	ZipEntry.cpp \
     	ZipFile.cpp
    @@ -71,12 +70,7 @@ ifeq ($(HOST_OS),linux)
     # Use the futex based mutex and condition variable
     # implementation from android-arm because it's shared mem safe
     	LOCAL_SRC_FILES += \
    -		futex_synchro.c \
    -		executablepath_linux.cpp
    -endif
    -ifeq ($(HOST_OS),darwin)
    -	LOCAL_SRC_FILES += \
    -		executablepath_darwin.cpp
    +		futex_synchro.c
     endif
     
     LOCAL_MODULE:= libutils
    diff --git a/libs/utils/Pipe.cpp b/libs/utils/Pipe.cpp
    deleted file mode 100644
    index 613906bedaa8f..0000000000000
    --- a/libs/utils/Pipe.cpp
    +++ /dev/null
    @@ -1,465 +0,0 @@
    -/*
    - * Copyright (C) 2005 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.
    - */
    -
    -//
    -// Unidirectional pipe.
    -//
    -
    -#include 
    -#include 
    -
    -#if defined(HAVE_WIN32_IPC)
    -# include 
    -#else
    -# include 
    -# include 
    -# include 
    -#endif
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -using namespace android;
    -
    -const unsigned long kInvalidHandle = (unsigned long) -1;
    -
    -
    -/*
    - * Constructor.  Do little.
    - */
    -Pipe::Pipe(void)
    -    : mReadNonBlocking(false), mReadHandle(kInvalidHandle),
    -      mWriteHandle(kInvalidHandle)
    -{
    -}
    -
    -/*
    - * Destructor.  Use the system-appropriate close call.
    - */
    -Pipe::~Pipe(void)
    -{
    -#if defined(HAVE_WIN32_IPC)
    -    if (mReadHandle != kInvalidHandle) {
    -        if (!CloseHandle((HANDLE)mReadHandle))
    -            LOG(LOG_WARN, "pipe", "failed closing read handle (%ld)\n",
    -                mReadHandle);
    -    }
    -    if (mWriteHandle != kInvalidHandle) {
    -        FlushFileBuffers((HANDLE)mWriteHandle);
    -        if (!CloseHandle((HANDLE)mWriteHandle))
    -            LOG(LOG_WARN, "pipe", "failed closing write handle (%ld)\n",
    -                mWriteHandle);
    -    }
    -#else
    -    if (mReadHandle != kInvalidHandle) {
    -        if (close((int) mReadHandle) != 0)
    -            LOG(LOG_WARN, "pipe", "failed closing read fd (%d)\n",
    -                (int) mReadHandle);
    -    }
    -    if (mWriteHandle != kInvalidHandle) {
    -        if (close((int) mWriteHandle) != 0)
    -            LOG(LOG_WARN, "pipe", "failed closing write fd (%d)\n",
    -                (int) mWriteHandle);
    -    }
    -#endif
    -}
    -
    -/*
    - * Create the pipe.
    - *
    - * Use the POSIX stuff for everything but Windows.
    - */
    -bool Pipe::create(void)
    -{
    -    assert(mReadHandle == kInvalidHandle);
    -    assert(mWriteHandle == kInvalidHandle);
    -
    -#if defined(HAVE_WIN32_IPC)
    -    /* we use this across processes, so they need to be inheritable */
    -    HANDLE handles[2];
    -    SECURITY_ATTRIBUTES saAttr;
    -
    -    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    -    saAttr.bInheritHandle = TRUE;
    -    saAttr.lpSecurityDescriptor = NULL;
    -
    -    if (!CreatePipe(&handles[0], &handles[1], &saAttr, 0)) {
    -        LOG(LOG_ERROR, "pipe", "unable to create pipe\n");
    -        return false;
    -    }
    -    mReadHandle = (unsigned long) handles[0];
    -    mWriteHandle = (unsigned long) handles[1];
    -    return true;
    -#else
    -    int fds[2];
    -
    -    if (pipe(fds) != 0) {
    -        LOG(LOG_ERROR, "pipe", "unable to create pipe\n");
    -        return false;
    -    }
    -    mReadHandle = fds[0];
    -    mWriteHandle = fds[1];
    -    return true;
    -#endif
    -}
    -
    -/*
    - * Create a "half pipe".  Please, no Segway riding.
    - */
    -bool Pipe::createReader(unsigned long handle)
    -{
    -    mReadHandle = handle;
    -    assert(mWriteHandle == kInvalidHandle);
    -    return true;
    -}
    -
    -/*
    - * Create a "half pipe" for writing.
    - */
    -bool Pipe::createWriter(unsigned long handle)
    -{
    -    mWriteHandle = handle;
    -    assert(mReadHandle == kInvalidHandle);
    -    return true;
    -}
    -
    -/*
    - * Return "true" if create() has been called successfully.
    - */
    -bool Pipe::isCreated(void)
    -{
    -    // one or the other should be open
    -    return (mReadHandle != kInvalidHandle || mWriteHandle != kInvalidHandle);
    -}
    -
    -
    -/*
    - * Read data from the pipe.
    - *
    - * For Linux and Darwin, just call read().  For Windows, implement
    - * non-blocking reads by calling PeekNamedPipe first.
    - */
    -int Pipe::read(void* buf, int count)
    -{
    -    assert(mReadHandle != kInvalidHandle);
    -
    -#if defined(HAVE_WIN32_IPC)
    -    DWORD totalBytesAvail = count;
    -    DWORD bytesRead;
    -
    -    if (mReadNonBlocking) {
    -        // use PeekNamedPipe to adjust read count expectations
    -        if (!PeekNamedPipe((HANDLE) mReadHandle, NULL, 0, NULL,
    -                &totalBytesAvail, NULL))
    -        {
    -            LOG(LOG_ERROR, "pipe", "PeekNamedPipe failed\n");
    -            return -1;
    -        }
    -
    -        if (totalBytesAvail == 0)
    -            return 0;
    -    }
    -
    -    if (!ReadFile((HANDLE) mReadHandle, buf, totalBytesAvail, &bytesRead,
    -            NULL))
    -    {
    -        DWORD err = GetLastError();
    -        if (err == ERROR_HANDLE_EOF || err == ERROR_BROKEN_PIPE)
    -            return 0;
    -        LOG(LOG_ERROR, "pipe", "ReadFile failed (err=%ld)\n", err);
    -        return -1;
    -    }
    -
    -    return (int) bytesRead;
    -#else
    -    int cc;
    -    cc = ::read(mReadHandle, buf, count);
    -    if (cc < 0 && errno == EAGAIN)
    -        return 0;
    -    return cc;
    -#endif
    -}
    -
    -/*
    - * Write data to the pipe.
    - *
    - * POSIX systems are trivial, Windows uses a different call and doesn't
    - * handle non-blocking writes.
    - *
    - * If we add non-blocking support here, we probably want to make it an
    - * all-or-nothing write.
    - *
    - * DO NOT use LOG() here, we could be writing a log message.
    - */
    -int Pipe::write(const void* buf, int count)
    -{
    -    assert(mWriteHandle != kInvalidHandle);
    -
    -#if defined(HAVE_WIN32_IPC)
    -    DWORD bytesWritten;
    -
    -    if (mWriteNonBlocking) {
    -        // BUG: can't use PeekNamedPipe() to get the amount of space
    -        // left.  Looks like we need to use "overlapped I/O" functions.
    -        // I just don't care that much.
    -    }
    -
    -    if (!WriteFile((HANDLE) mWriteHandle, buf, count, &bytesWritten, NULL)) {
    -        // can't LOG, use stderr
    -        fprintf(stderr, "WriteFile failed (err=%ld)\n", GetLastError());
    -        return -1;
    -    }
    -
    -    return (int) bytesWritten;
    -#else
    -    int cc;
    -    cc = ::write(mWriteHandle, buf, count);
    -    if (cc < 0 && errno == EAGAIN)
    -        return 0;
    -    return cc;
    -#endif
    -}
    -
    -/*
    - * Figure out if there is data available on the read fd.
    - *
    - * We return "true" on error because we want the caller to try to read
    - * from the pipe.  They'll notice the read failure and do something
    - * appropriate.
    - */
    -bool Pipe::readReady(void)
    -{
    -    assert(mReadHandle != kInvalidHandle);
    -
    -#if defined(HAVE_WIN32_IPC)
    -    DWORD totalBytesAvail;
    -
    -    if (!PeekNamedPipe((HANDLE) mReadHandle, NULL, 0, NULL,
    -            &totalBytesAvail, NULL))
    -    {
    -        LOG(LOG_ERROR, "pipe", "PeekNamedPipe failed\n");
    -        return true;
    -    }
    -
    -    return (totalBytesAvail != 0);
    -#else
    -    errno = 0;
    -    fd_set readfds;
    -    struct timeval tv = { 0, 0 };
    -    int cc;
    -
    -    FD_ZERO(&readfds);
    -    FD_SET(mReadHandle, &readfds);
    -
    -    cc = select(mReadHandle+1, &readfds, NULL, NULL, &tv);
    -    if (cc < 0) {
    -        LOG(LOG_ERROR, "pipe", "select() failed\n");
    -        return true;
    -    } else if (cc == 0) {
    -        /* timed out, nothing available */
    -        return false;
    -    } else if (cc == 1) {
    -        /* our fd is ready */
    -        return true;
    -    } else {
    -        LOG(LOG_ERROR, "pipe", "HUH? select() returned > 1\n");
    -        return true;
    -    }
    -#endif
    -}
    -
    -/*
    - * Enable or disable non-blocking mode for the read descriptor.
    - *
    - * NOTE: the calls succeed under Mac OS X, but the pipe doesn't appear to
    - * actually be in non-blocking mode.  If this matters -- i.e. you're not
    - * using a select() call -- put a call to readReady() in front of the
    - * ::read() call, with a PIPE_NONBLOCK_BROKEN #ifdef in the Makefile for
    - * Darwin.
    - */
    -bool Pipe::setReadNonBlocking(bool val)
    -{
    -    assert(mReadHandle != kInvalidHandle);
    -
    -#if defined(HAVE_WIN32_IPC)
    -    // nothing to do
    -#else
    -    int flags;
    -
    -    if (fcntl(mReadHandle, F_GETFL, &flags) == -1) {
    -        LOG(LOG_ERROR, "pipe", "couldn't get flags for pipe read fd\n");
    -        return false;
    -    }
    -    if (val)
    -        flags |= O_NONBLOCK;
    -    else
    -        flags &= ~(O_NONBLOCK);
    -    if (fcntl(mReadHandle, F_SETFL, &flags) == -1) {
    -        LOG(LOG_ERROR, "pipe", "couldn't set flags for pipe read fd\n");
    -        return false;
    -    }
    -#endif
    -
    -    mReadNonBlocking = val;
    -    return true;
    -}
    -
    -/*
    - * Enable or disable non-blocking mode for the write descriptor.
    - *
    - * As with setReadNonBlocking(), this does not work on the Mac.
    - */
    -bool Pipe::setWriteNonBlocking(bool val)
    -{
    -    assert(mWriteHandle != kInvalidHandle);
    -
    -#if defined(HAVE_WIN32_IPC)
    -    // nothing to do
    -#else
    -    int flags;
    -
    -    if (fcntl(mWriteHandle, F_GETFL, &flags) == -1) {
    -        LOG(LOG_WARN, "pipe",
    -            "Warning: couldn't get flags for pipe write fd (errno=%d)\n",
    -            errno);
    -        return false;
    -    }
    -    if (val)
    -        flags |= O_NONBLOCK;
    -    else
    -        flags &= ~(O_NONBLOCK);
    -    if (fcntl(mWriteHandle, F_SETFL, &flags) == -1) {
    -        LOG(LOG_WARN, "pipe",
    -            "Warning: couldn't set flags for pipe write fd (errno=%d)\n",
    -            errno);
    -        return false;
    -    }
    -#endif
    -
    -    mWriteNonBlocking = val;
    -    return true;
    -}
    -
    -/*
    - * Specify whether a file descriptor can be inherited by a child process.
    - * Under Linux this means setting the close-on-exec flag, under Windows
    - * this is SetHandleInformation(HANDLE_FLAG_INHERIT).
    - */
    -bool Pipe::disallowReadInherit(void)
    -{
    -    if (mReadHandle == kInvalidHandle)
    -        return false;
    -
    -#if defined(HAVE_WIN32_IPC)
    -    if (SetHandleInformation((HANDLE) mReadHandle, HANDLE_FLAG_INHERIT, 0) == 0)
    -        return false;
    -#else
    -    if (fcntl((int) mReadHandle, F_SETFD, FD_CLOEXEC) != 0)
    -        return false;
    -#endif
    -    return true;
    -}
    -bool Pipe::disallowWriteInherit(void)
    -{
    -    if (mWriteHandle == kInvalidHandle)
    -        return false;
    -
    -#if defined(HAVE_WIN32_IPC)
    -    if (SetHandleInformation((HANDLE) mWriteHandle, HANDLE_FLAG_INHERIT, 0) == 0)
    -        return false;
    -#else
    -    if (fcntl((int) mWriteHandle, F_SETFD, FD_CLOEXEC) != 0)
    -        return false;
    -#endif
    -    return true;
    -}
    -
    -/*
    - * Close read descriptor.
    - */
    -bool Pipe::closeRead(void)
    -{
    -    if (mReadHandle == kInvalidHandle)
    -        return false;
    -
    -#if defined(HAVE_WIN32_IPC)
    -    if (mReadHandle != kInvalidHandle) {
    -        if (!CloseHandle((HANDLE)mReadHandle)) {
    -            LOG(LOG_WARN, "pipe", "failed closing read handle\n");
    -            return false;
    -        }
    -    }
    -#else
    -    if (mReadHandle != kInvalidHandle) {
    -        if (close((int) mReadHandle) != 0) {
    -            LOG(LOG_WARN, "pipe", "failed closing read fd\n");
    -            return false;
    -        }
    -    }
    -#endif
    -    mReadHandle = kInvalidHandle;
    -    return true;
    -}
    -
    -/*
    - * Close write descriptor.
    - */
    -bool Pipe::closeWrite(void)
    -{
    -    if (mWriteHandle == kInvalidHandle)
    -        return false;
    -
    -#if defined(HAVE_WIN32_IPC)
    -    if (mWriteHandle != kInvalidHandle) {
    -        if (!CloseHandle((HANDLE)mWriteHandle)) {
    -            LOG(LOG_WARN, "pipe", "failed closing write handle\n");
    -            return false;
    -        }
    -    }
    -#else
    -    if (mWriteHandle != kInvalidHandle) {
    -        if (close((int) mWriteHandle) != 0) {
    -            LOG(LOG_WARN, "pipe", "failed closing write fd\n");
    -            return false;
    -        }
    -    }
    -#endif
    -    mWriteHandle = kInvalidHandle;
    -    return true;
    -}
    -
    -/*
    - * Get the read handle.
    - */
    -unsigned long Pipe::getReadHandle(void)
    -{
    -    assert(mReadHandle != kInvalidHandle);
    -
    -    return mReadHandle;
    -}
    -
    -/*
    - * Get the write handle.
    - */
    -unsigned long Pipe::getWriteHandle(void)
    -{
    -    assert(mWriteHandle != kInvalidHandle);
    -
    -    return mWriteHandle;
    -}
    -
    diff --git a/libs/utils/executablepath_darwin.cpp b/libs/utils/executablepath_darwin.cpp
    deleted file mode 100644
    index 2e3c3a01f5df7..0000000000000
    --- a/libs/utils/executablepath_darwin.cpp
    +++ /dev/null
    @@ -1,31 +0,0 @@
    -/*
    - * Copyright (C) 2008 The Android Open Source Project
    - *
    - * Licensed under the Apache License, Version 2.0 (the "License");
    - * you may not use this file except in compliance with the License.
    - * You may obtain a copy of the License at
    - *
    - *      http://www.apache.org/licenses/LICENSE-2.0
    - *
    - * Unless required by applicable law or agreed to in writing, software
    - * distributed under the License is distributed on an "AS IS" BASIS,
    - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    - * See the License for the specific language governing permissions and
    - * limitations under the License.
    - */
    -
    -#include 
    -#import 
    -#include 
    -
    -void executablepath(char s[PATH_MAX])
    -{
    -    ProcessSerialNumber psn;
    -    GetCurrentProcess(&psn);
    -    CFDictionaryRef dict;
    -    dict = ProcessInformationCopyDictionary(&psn, 0xffffffff);
    -    CFStringRef value = (CFStringRef)CFDictionaryGetValue(dict,
    -                CFSTR("CFBundleExecutable"));
    -    CFStringGetCString(value, s, PATH_MAX+1, kCFStringEncodingUTF8);
    -}
    -
    diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
    index 19ab0add2b914..d3743e6607b8a 100644
    --- a/media/java/android/media/MediaPlayer.java
    +++ b/media/java/android/media/MediaPlayer.java
    @@ -468,6 +468,11 @@ public class MediaPlayer
              */
             native_setup(new WeakReference(this));
         }
    +
    +    /*
    +     * Update the MediaPlayer ISurface. Call after updating mSurface.
    +     */
    +    private native void _setVideoSurface();
       
         /**
          * Sets the SurfaceHolder to use for displaying the video portion of the media.
    @@ -478,7 +483,12 @@ public class MediaPlayer
          */
         public void setDisplay(SurfaceHolder sh) {
             mSurfaceHolder = sh;
    -        mSurface = sh.getSurface();
    +        if (sh != null) {
    +            mSurface = sh.getSurface();
    +        } else {
    +            mSurface = null;
    +        }
    +        _setVideoSurface();
             updateSurfaceScreenOn();
         }
     
    diff --git a/media/java/android/media/ToneGenerator.java b/media/java/android/media/ToneGenerator.java
    index 4b53756db118a..54ca6c40c5637 100644
    --- a/media/java/android/media/ToneGenerator.java
    +++ b/media/java/android/media/ToneGenerator.java
    @@ -19,11 +19,11 @@ package android.media;
     
     
     /**
    - * This class provides methods to play DTMF tones (ITU-T Recommendation Q.23), 
    - * call supervisory tones (3GPP TS 22.001, CEPT) and proprietary tones (3GPP TS 31.111). 
    + * This class provides methods to play DTMF tones (ITU-T Recommendation Q.23),
    + * call supervisory tones (3GPP TS 22.001, CEPT) and proprietary tones (3GPP TS 31.111).
      * Depending on call state and routing options, tones are mixed to the downlink audio
    - * or output to the speaker phone or headset. 
    - * This API is not for generating tones over the uplink audio path.   
    + * or output to the speaker phone or headset.
    + * This API is not for generating tones over the uplink audio path.
      */
     public class ToneGenerator
     {
    @@ -33,99 +33,99 @@ public class ToneGenerator
          * List of all available tones: These constants must be kept consistant with
          * the enum in ToneGenerator C++ class.     */
     
    -	/**
    +    /**
          * DTMF tone for key 0: 1336Hz, 941Hz, continuous

    - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_0 = 0; /** * DTMF tone for key 1: 1209Hz, 697Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_1 = 1; /** * DTMF tone for key 2: 1336Hz, 697Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_2 = 2; /** * DTMF tone for key 3: 1477Hz, 697Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_3 = 3; /** * DTMF tone for key 4: 1209Hz, 770Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_4 = 4; /** * DTMF tone for key 5: 1336Hz, 770Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_5 = 5; /** * DTMF tone for key 6: 1477Hz, 770Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_6 = 6; /** * DTMF tone for key 7: 1209Hz, 852Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_7 = 7; /** * DTMF tone for key 8: 1336Hz, 852Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_8 = 8; /** * DTMF tone for key 9: 1477Hz, 852Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_9 = 9; /** * DTMF tone for key *: 1209Hz, 941Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_S = 10; /** * DTMF tone for key #: 1477Hz, 941Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_P = 11; /** * DTMF tone for key A: 1633Hz, 697Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_A = 12; /** * DTMF tone for key B: 1633Hz, 770Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_B = 13; /** * DTMF tone for key C: 1633Hz, 852Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_C = 14; /** * DTMF tone for key D: 1633Hz, 941Hz, continuous - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_DTMF_D = 15; @@ -151,7 +151,7 @@ public class ToneGenerator * Call supervisory tone, Congestion: * CEPT, JAPAN: 425Hz, 200ms ON, 200ms OFF... * ANSI (IS-95): 480Hz+620Hz, 250ms ON, 250ms OFF... - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_SUP_CONGESTION = 18; @@ -159,27 +159,28 @@ public class ToneGenerator * Call supervisory tone, Radio path acknowlegment : * CEPT, ANSI: 425Hz, 200ms ON * JAPAN: 400Hz, 1s ON, 2s OFF... - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_SUP_RADIO_ACK = 19; /** * Call supervisory tone, Radio path not available: 425Hz, 200ms ON, 200 OFF 3 bursts - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_SUP_RADIO_NOTAVAIL = 20; /** * Call supervisory tone, Error/Special info: 950Hz+1400Hz+1800Hz, 330ms ON, 1s OFF... - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_SUP_ERROR = 21; /** * Call supervisory tone, Call Waiting: * CEPT, JAPAN: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF... - * ANSI (IS-95): 440 Hz, 300 ms ON, 9.7 s OFF, (100 ms ON, 100 ms OFF, 100 ms ON, 9.7s OFF ...) - * + * ANSI (IS-95): 440 Hz, 300 ms ON, 9.7 s OFF, + * (100 ms ON, 100 ms OFF, 100 ms ON, 9.7s OFF ...) + * * @see #ToneGenerator(int, int) */ public static final int TONE_SUP_CALL_WAITING = 22; @@ -187,42 +188,43 @@ public class ToneGenerator * Call supervisory tone, Ring Tone: * CEPT, JAPAN: 425Hz, 1s ON, 4s OFF... * ANSI (IS-95): 440Hz + 480Hz, 2s ON, 4s OFF... - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_SUP_RINGTONE = 23; /** * Proprietary tone, general beep: 400Hz+1200Hz, 35ms ON - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_PROP_BEEP = 24; /** * Proprietary tone, positive acknowlegement: 1200Hz, 100ms ON, 100ms OFF 2 bursts - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_PROP_ACK = 25; /** * Proprietary tone, negative acknowlegement: 300Hz+400Hz+500Hz, 400ms ON - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_PROP_NACK = 26; /** * Proprietary tone, prompt tone: 400Hz+1200Hz, 200ms ON - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_PROP_PROMPT = 27; /** * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON - * + * * @see #ToneGenerator(int, int) */ public static final int TONE_PROP_BEEP2 = 28; /** - * Call supervisory tone (IS-95), intercept tone: alternating 440 Hz and 620 Hz tones, each on for 250 ms + * Call supervisory tone (IS-95), intercept tone: alternating 440 Hz and 620 Hz tones, + * each on for 250 ms * * @see #ToneGenerator(int, int) */ @@ -240,7 +242,8 @@ public class ToneGenerator */ public static final int TONE_SUP_CONGESTION_ABBREV = 31; /** - * Call supervisory tone (IS-95), confirm tone: a 350 Hz tone added to a 440 Hz tone repeated 3 times in a 100 ms on, 100 ms off cycle + * Call supervisory tone (IS-95), confirm tone: a 350 Hz tone added to a 440 Hz tone + * repeated 3 times in a 100 ms on, 100 ms off cycle * * @see #ToneGenerator(int, int) */ @@ -253,6 +256,241 @@ public class ToneGenerator public static final int TONE_SUP_PIP = 33; + /** + * CDMA SPECIFIC TONES START + */ + + /** TODO(Moto): Change "Proprietary" below with an appropriate specification reference */ + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_DIAL_TONE_LITE = 34; + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_NETWORK_USA_RINGBACK = 35; + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_REORDER = 36; + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_ABBR_REORDER = 37; + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_NETWORK_BUSY = 38; + + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_ANSWER = 39; + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_NETWORK_CALLWAITING = 40; + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_PIP = 41; + + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL = 42; + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP = 43; + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_CALL_SIGNAL_SP_PRI = 44; + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT3 = 45; + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_CALL_SIGNAL_ISDN_RING_RING = 46; + + /** + * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT5 = 47; + + /** + * general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT6 = 48; + + /** + * general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON + * + * @see #ToneGenerator(int, int) + * + * @hide + */ + public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT7 = 49; + + // TODO(Moto): Need comments for each one and we need ToneGenerator.cpp/ToneGenerator.h + + /** @hide */ + public static final int TONE_CDMA_HIGH_L = 50; + + /** @hide */ + public static final int TONE_CDMA_LOW_L = 51; + /** @hide */ + public static final int TONE_CDMA_HIGH_SS = 52; + /** @hide */ + public static final int TONE_CDMA_MED_SS = 53; + /** @hide */ + public static final int TONE_CDMA_LOW_SS = 54; + /** @hide */ + public static final int TONE_CDMA_HIGH_SSL = 55; + + + /** @hide */ + public static final int TONE_CDMA_MED_SSL = 56; + /** @hide */ + public static final int TONE_CDMA_LOW_SSL = 57; + /** @hide */ + public static final int TONE_CDMA_HIGH_SS_2 = 58; + /** @hide */ + public static final int TONE_CDMA_MED_SS_2 = 59; + /** @hide */ + public static final int TONE_CDMA_LOW_SS_2 = 60; + /** @hide */ + public static final int TONE_CDMA_HIGH_SLS = 61; + /** @hide */ + public static final int TONE_CDMA_MED_SLS = 62; + /** @hide */ + public static final int TONE_CDMA_LOW_SLS = 63; + /** @hide */ + public static final int TONE_CDMA_HIGH_S_X4 = 64; + /** @hide */ + public static final int TONE_CDMA_MED_S_X4 = 65; + /** @hide */ + public static final int TONE_CDMA_LOW_S_X4 = 66; + /** @hide */ + public static final int TONE_CDMA_HIGH_PBX_L = 67; + /** @hide */ + public static final int TONE_CDMA_MED_PBX_L = 68; + /** @hide */ + public static final int TONE_CDMA_LOW_PBX_L = 69; + /** @hide */ + public static final int TONE_CDMA_HIGH_PBX_SS = 70; + /** @hide */ + public static final int TONE_CDMA_MED_PBX_SS = 71; + /** @hide */ + public static final int TONE_CDMA_LOW_PBX_SS = 72; + /** @hide */ + public static final int TONE_CDMA_HIGH_PBX_SSL = 73; + /** @hide */ + public static final int TONE_CDMA_MED_PBX_SSL = 74; + + /** @hide */ + public static final int TONE_CDMA_LOW_PBX_SSL = 75; + /** @hide */ + public static final int TONE_CDMA_HIGH_PBX_SLS = 76; + /** @hide */ + public static final int TONE_CDMA_MED_PBX_SLS = 77; + /** @hide */ + public static final int TONE_CDMA_LOW_PBX_SLS = 78; + /** @hide */ + public static final int TONE_CDMA_HIGH_PBX_S_X4 = 79; + /** @hide */ + public static final int TONE_CDMA_MED_PBX_S_X4 = 80; + /** @hide */ + public static final int TONE_CDMA_LOW_PBX_S_X4 = 81; + /** @hide */ + public static final int TONE_CDMA_INTERCEPT_ONE_SHOT = TONE_SUP_INTERCEPT_ABBREV; + /** @hide */ + public static final int TONE_CDMA_REORDER_ONE_SHOT = TONE_CDMA_ABBR_REORDER; + /** @hide */ + public static final int TONE_CDMA_NETWORK_BUSY_ONE_SHOT = 82; + /** @hide */ + public static final int TONE_CDMA_ABBR_ALERT = 83; + /** @hide */ + public static final int TONE_CDMA_SIGNAL_OFF = 84; + /** @hide */ + public static final int TONE_CDMA_INVALID = 85; + /** Maximum volume, for use with {@link #ToneGenerator(int,int)} */ public static final int MAX_VOLUME = AudioSystem.MAX_VOLUME; /** Minimum volume setting, for use with {@link #ToneGenerator(int,int)} */ @@ -261,10 +499,10 @@ public class ToneGenerator /** * ToneGenerator class contructor specifying output stream type and volume. - * + * * @param streamType The streame type used for tone playback (e.g. STREAM_MUSIC). * @param volume The volume of the tone, given in percentage of maximum volume (from 0-100). - * + * */ public ToneGenerator(int streamType, int volume) { native_setup(streamType, volume); @@ -272,7 +510,7 @@ public class ToneGenerator /** * This method starts the playback of a tone of the specified type. - * only one tone can play at a time: if a tone is playing while this method is called, + * only one tone can play at a time: if a tone is playing while this method is called, * this tone is stopped and replaced by the one requested. * @param toneType The type of tone generate chosen from the following list: *
      @@ -328,9 +566,10 @@ public class ToneGenerator private native final void native_setup(int streamType, int volume); private native final void native_finalize(); + + @Override protected void finalize() { native_finalize(); } + @SuppressWarnings("unused") private int mNativeContext; // accessed by native methods - - } diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index 707db02fd9488..5abe451ca135c 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -198,6 +198,27 @@ android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fil process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." ); } +static void setVideoSurface(const sp& mp, JNIEnv *env, jobject thiz) +{ + jobject surface = env->GetObjectField(thiz, fields.surface); + if (surface != NULL) { + const sp& native_surface = get_surface(env, surface); + LOGV("prepare: surface=%p (id=%d)", + native_surface.get(), native_surface->ID()); + mp->setVideoSurface(native_surface); + } +} + +static void +android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz) +{ + sp mp = getMediaPlayer(env, thiz); + if (mp == NULL ) { + jniThrowException(env, "java/lang/IllegalStateException", NULL); + return; + } + setVideoSurface(mp, env, thiz); +} static void android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz) @@ -207,13 +228,7 @@ android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz) jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } - jobject surface = env->GetObjectField(thiz, fields.surface); - if (surface != NULL) { - const sp& native_surface = get_surface(env, surface); - LOGV("prepare: surface=%p (id=%d)", - native_surface.get(), native_surface->ID()); - mp->setVideoSurface(native_surface); - } + setVideoSurface(mp, env, thiz); process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." ); } @@ -469,6 +484,7 @@ android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz) static JNINativeMethod gMethods[] = { {"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaPlayer_setDataSource}, {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD}, + {"_setVideoSurface", "()V", (void *)android_media_MediaPlayer_setVideoSurface}, {"prepare", "()V", (void *)android_media_MediaPlayer_prepare}, {"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync}, {"_start", "()V", (void *)android_media_MediaPlayer_start}, diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java index 50cbb34851b70..2ff0c9d24815b 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java @@ -68,6 +68,13 @@ public class MediaPlayerPerformance extends ActivityInstrumentationTestCase * * @see #onSignalStrengthChanged @@ -52,6 +55,9 @@ public class PhoneStateListener { /** * Listen for changes to the message-waiting indicator. + * {@more} + * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE + * READ_PHONE_STATE} *

      * Example: The status bar uses this to determine when to display the * voicemail icon. @@ -62,7 +68,9 @@ public class PhoneStateListener { /** * Listen for changes to the call-forwarding indicator. - * + * {@more} + * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE + * READ_PHONE_STATE} * @see #onCallForwardingIndicatorChanged */ public static final int LISTEN_CALL_FORWARDING_INDICATOR = 0x00000008; @@ -85,7 +93,9 @@ public class PhoneStateListener { /** * Listen for changes to the device call state. - * + * {@more} + * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE + * READ_PHONE_STATE} * @see #onCallStateChanged */ public static final int LISTEN_CALL_STATE = 0x00000020; @@ -100,7 +110,9 @@ public class PhoneStateListener { /** * Listen for changes to the direction of data traffic on the data * connection (cellular). - * + * {@more} + * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE + * READ_PHONE_STATE} * Example: The status bar uses this to display the appropriate * data-traffic icon. * diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java index e78422e449de4..dba497250314a 100644 --- a/telephony/java/com/android/internal/telephony/BaseCommands.java +++ b/telephony/java/com/android/internal/telephony/BaseCommands.java @@ -54,10 +54,11 @@ public abstract class BaseCommands implements CommandsInterface { protected RegistrantList mIccStatusChangedRegistrants = new RegistrantList(); protected RegistrantList mVoicePrivacyOnRegistrants = new RegistrantList(); protected RegistrantList mVoicePrivacyOffRegistrants = new RegistrantList(); - protected RegistrantList mOtaSessionRegistrants = new RegistrantList(); - protected RegistrantList mCallWaitingRegistrants = new RegistrantList(); - protected RegistrantList mInformationRecordsRegistrants = new RegistrantList(); protected Registrant mUnsolOemHookRawRegistrant; + protected RegistrantList mOtaProvisionRegistrants = new RegistrantList(); + protected RegistrantList mCallWaitingInfoRegistrants = new RegistrantList(); + protected RegistrantList mDisplayInfoRegistrants = new RegistrantList(); + protected RegistrantList mSignalInfoRegistrants = new RegistrantList(); protected Registrant mSMSRegistrant; protected Registrant mNITZTimeRegistrant; protected Registrant mSignalStrengthRegistrant; @@ -464,6 +465,29 @@ public abstract class BaseCommands implements CommandsInterface { mRestrictedStateRegistrant.clear(); } + public void registerForDisplayInfo(Handler h, int what, Object obj) { + Registrant r = new Registrant (h, what, obj); + mDisplayInfoRegistrants.add(r); + } + + public void unregisterForDisplayInfo(Handler h) { + mDisplayInfoRegistrants.remove(h); + } + + public void registerForCallWaitingInfo(Handler h, int what, Object obj) { + Registrant r = new Registrant (h, what, obj); + mCallWaitingInfoRegistrants.add(r); + } + + public void unregisterForCallWaitingInfo(Handler h) { + mCallWaitingInfoRegistrants.remove(h); + } + + public void registerForSignalInfo(Handler h, int what, Object obj) { + Registrant r = new Registrant (h, what, obj); + mSignalInfoRegistrants.add(r); + } + public void setOnUnsolOemHookRaw(Handler h, int what, Object obj) { mUnsolOemHookRawRegistrant = new Registrant (h, what, obj); } @@ -472,32 +496,19 @@ public abstract class BaseCommands implements CommandsInterface { mUnsolOemHookRawRegistrant.clear(); } - public void registerForOtaSessionStatus(Handler h, int what, Object obj){ + public void unregisterForSignalInfo(Handler h) { + mSignalInfoRegistrants.remove(h); + } + + public void registerForCdmaOtaProvision(Handler h,int what, Object obj){ Registrant r = new Registrant (h, what, obj); - mOtaSessionRegistrants.add(r); + mOtaProvisionRegistrants.add(r); } - public void unregisterForOtaSessionStatus(Handler h){ - mOtaSessionRegistrants.remove(h); + public void unregisterForCdmaOtaProvision(Handler h){ + mOtaProvisionRegistrants.remove(h); } - public void registerForCdmaCallWaiting(Handler h, int what, Object obj){ - Registrant r = new Registrant (h, what, obj); - mCallWaitingRegistrants.add(r); - } - - public void unregisterForCdmaCallWaiting(Handler h){ - mCallWaitingRegistrants.remove(h); - } - - public void registerCdmaInformationRecord(Handler h, int what, Object obj) { - Registrant r = new Registrant (h, what, obj); - mInformationRecordsRegistrants.add(r); - } - - public void unregisterCdmaInformationRecord(Handler h) { - mInformationRecordsRegistrants.remove(h); - } //***** Protected Methods /** diff --git a/telephony/java/com/android/internal/telephony/CallTracker.java b/telephony/java/com/android/internal/telephony/CallTracker.java index eb339f869b8ab..8263ded7a2866 100644 --- a/telephony/java/com/android/internal/telephony/CallTracker.java +++ b/telephony/java/com/android/internal/telephony/CallTracker.java @@ -56,6 +56,7 @@ public abstract class CallTracker extends Handler { protected static final int EVENT_CONFERENCE_RESULT = 11; protected static final int EVENT_SEPARATE_RESULT = 12; protected static final int EVENT_ECT_RESULT = 13; + protected static final int EVENT_EXIT_ECM_RESPONSE_CDMA = 14; protected void pollCallsWhenSafe() { diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index da53e15e93ede..32f31ef4c14bb 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -70,6 +70,12 @@ public class CallerInfo { */ public String name; public String phoneNumber; + + public String cnapName; + public int numberPresentation; + public int namePresentation; + public boolean contactExists; + public String phoneLabel; /* Split up the phoneLabel into number type and label name */ public int numberType; @@ -118,6 +124,7 @@ public class CallerInfo { info.numberLabel = null; info.cachedPhoto = null; info.isCachedPhotoCurrent = false; + info.contactExists = false; if (Config.LOGV) Log.v(TAG, "construct callerInfo from cursor"); @@ -176,6 +183,7 @@ public class CallerInfo { columnIndex = cursor.getColumnIndex(People.SEND_TO_VOICEMAIL); info.shouldSendToVoicemail = (columnIndex != -1) && ((cursor.getInt(columnIndex)) == 1); + info.contactExists = true; } cursor.close(); } @@ -303,4 +311,3 @@ public class CallerInfo { } } } - diff --git a/telephony/java/com/android/internal/telephony/CdmaInformationRecord.java b/telephony/java/com/android/internal/telephony/CdmaInformationRecord.java deleted file mode 100644 index 690df058b59bc..0000000000000 --- a/telephony/java/com/android/internal/telephony/CdmaInformationRecord.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.telephony; - -/** - * TODO(Teleca): This class was poorly implemented and didn't - * follow the Android coding conventions. It is now more or less - * follows the conventions but there is still some work, see the - * TODO's. - */ - - -public class CdmaInformationRecord { - public int messageName; - - public CdmaDisplayInfoRec displayInfoRec; - public CdmaNumberInfoRec numberInfoRec; - public CdmaSignalInfoRec signalInfoRec; - public CdmaRedirectingNumberInfoRec redirectingNumberInfoRec; - public CdmaLineControlInfoRec lineControlInfoRec; - public CdmaT53ClirInfoRec cdmaT53ClirInfoRec; - public CdmaT53AudioControlInfoRec cdmaT53AudioControlInfoRec; - - public static final int RIL_CDMA_DISPLAY_INFO_REC = 0; - public static final int RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC = 1; - public static final int RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC = 2; - public static final int RIL_CDMA_CONNECTED_NUMBER_INFO_REC = 3; - public static final int RIL_CDMA_SIGNAL_INFO_REC = 4; - public static final int RIL_CDMA_REDIRECTING_NUMBER_INFO_REC = 5; - public static final int RIL_CDMA_LINE_CONTROL_INFO_REC = 6; - public static final int RIL_CDMA_EXTENDED_DISPLAY_INFO_REC = 7; - public static final int RIL_CDMA_T53_CLIR_INFO_REC = 8; - public static final int RIL_CDMA_T53_RELEASE_INFO_REC = 9; - public static final int RIL_CDMA_T53_AUDIO_CONTROL_INFO_REC = 10; - - public CdmaInformationRecord(int messageName) { - this.messageName = messageName; - } - - void createDisplayInfo(int length, char buffer[]) { - displayInfoRec = new CdmaDisplayInfoRec(length, buffer); - } - - void createNumberInfo(int length, char buffer[]) { - numberInfoRec = new CdmaNumberInfoRec(length, buffer); - } - - void createSignalInfo(char buffer[]) { - signalInfoRec = new CdmaSignalInfoRec(buffer); - } - - void createRedirectingNumberInfo(int length, char buffer[], int reason) { - redirectingNumberInfoRec = new CdmaRedirectingNumberInfoRec(length, buffer, reason); - } - - void createLineControlInfo(char buffer[]) { - lineControlInfoRec = new CdmaLineControlInfoRec(buffer); - } - - void createT53ClirInfo(char buffer) { - cdmaT53ClirInfoRec = new CdmaT53ClirInfoRec(buffer); - } - - void createT53AudioControlInfo(char ul, char dl) { - cdmaT53AudioControlInfoRec = new CdmaT53AudioControlInfoRec(ul, dl); - } - - /** - * TODO(Teleca): Add comments for each class giving the - * document and section where the information is defined - * as shown CdmaSignalInfoRec. Also add a toString to - * each of these to ease debugging. - */ - - /** - * Signal Information record from 3GPP2 C.S005 3.7.5.5 - */ - public static class CdmaSignalInfoRec { - public boolean isPresent; /* non-zero if signal information record is present */ - public int signalType; - public int alertPitch; - public int signalCode; - - public CdmaSignalInfoRec() {} - - public CdmaSignalInfoRec(char buffer[]) { - isPresent = buffer[0] == 1; - signalType = buffer[1]; - alertPitch = buffer[2]; - signalCode = buffer[3]; - } - - @Override - public String toString() { - return "CdmaSignalInfo: {" + - " isPresent: " + isPresent + - ", signalType: " + signalType + - ", alertPitch: " + alertPitch + - ", signalCode: " + signalCode + - " }"; - } - } - - public static class CdmaDisplayInfoRec { - public char alphaLen; - public char alphaBuf[]; - - public CdmaDisplayInfoRec(int length, char buffer[]) { - alphaLen = (char)length; - alphaBuf = new char[length]; - for(int i = 0; i < length; i++) - alphaBuf[i] = buffer[i]; - } - } - - public static class CdmaNumberInfoRec { - public int len; - public char buf[]; - public char numberType; - public char numberPlan; - public char pi; // TODO(Teleca): poor name, no meaning - public char si; // TODO(Teleca): poor name - - public CdmaNumberInfoRec(int length, char buffer[]) { - int i; - - len = length; - buf = new char[length]; - for (i = 0; i < len; i++) { - buf[i] = buffer[i]; - } - - numberType = buffer[i++]; - numberPlan = buffer[i++]; - pi = buffer[i++]; - si = buffer[i++]; - } - } - - public static class CdmaRedirectingNumberInfoRec { - public static final int REASON_UNKNOWN = 0; - public static final int REASON_CALL_FORWARDING_BUSY = 1; - public static final int REASON_CALL_FORWARDING_NO_REPLY = 2; - public static final int REASON_CALLED_DTE_OUT_OF_ORDER = 9; - public static final int REASON_CALL_FORWARDING_BY_THE_CALLED_DTE = 10; - public static final int REASON_CALL_FORWARDING_UNCONDITIONAL = 15; - - public CdmaNumberInfoRec numberInfoRec; - public int redirectingReason; - - public CdmaRedirectingNumberInfoRec(int length, char buffer[], int reason) { - numberInfoRec = new CdmaNumberInfoRec(length, buffer); - redirectingReason = reason; - } - } - - public static class CdmaLineControlInfoRec { - public char lineCtrlPolarityIncluded; - public char lineCtrlToggle; - public char lineCtrlReverse; - public char lineCtrlPowerDenial; - - CdmaLineControlInfoRec(char buffer[]) { - lineCtrlPolarityIncluded = buffer[0]; - lineCtrlToggle = buffer[1]; - lineCtrlReverse = buffer[2]; - lineCtrlPowerDenial = buffer[3]; - } - } - - // TODO(Teleca): A class for a single character, is this needed? - public static class CdmaT53ClirInfoRec { - public char cause; - - public CdmaT53ClirInfoRec(char buffer) { - cause = buffer; - } - } - - public static class CdmaT53AudioControlInfoRec { - public char uplink; - public char downlink; - - public CdmaT53AudioControlInfoRec(char ul, char dl) { - uplink = ul; - downlink = dl; - } - } -} diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java index ddf6b50f6f203..34a57a026d95a 100644 --- a/telephony/java/com/android/internal/telephony/CommandsInterface.java +++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java @@ -147,6 +147,14 @@ public interface CommandsInterface { static final int SIM_REFRESH_INIT = 1; // SIM initialized; reload all static final int SIM_REFRESH_RESET = 2; // SIM reset; may be locked + // GSM SMS fail cause for acknowledgeLastIncomingSMS. From TS 23.040, 9.2.3.22. + static final int GSM_SMS_FAIL_CAUSE_MEMORY_CAPACITY_EXCEEDED = 0xD3; + static final int GSM_SMS_FAIL_CAUSE_UNSPECIFIED_ERROR = 0xFF; + + // CDMA SMS fail cause for acknowledgeLastIncomingCdmaSms. From TS N.S00005, 6.5.2.125. + static final int CDMA_SMS_FAIL_CAUSE_RESOURCE_SHORTAGE = 35; + static final int CDMA_SMS_FAIL_CAUSE_OTHER_TERMINAL_PROBLEM = 39; + //***** Methods RadioState getRadioState(); @@ -240,24 +248,6 @@ public interface CommandsInterface { void registerForRUIMReady(Handler h, int what, Object obj); void unregisterForRUIMReady(Handler h); - /** - * Registers for the status of an OTASP/OTAPA session - */ - void registerForOtaSessionStatus(Handler h, int what, Object obj); - void unregisterForOtaSessionStatus(Handler h); - - /** - * register for Call waiting for CDMA - */ - void registerForCdmaCallWaiting(Handler h, int what, Object obj); - void unregisterForCdmaCallWaiting(Handler h); - - /** - * Registers for CDMA information records - */ - void registerCdmaInformationRecord(Handler h, int what, Object obj); - void unregisterCdmaInformationRecord(Handler h); - /** * unlike the register* methods, there's only one new SMS handler * if you need to unregister, you should also tell the radio to stop @@ -343,16 +333,6 @@ public interface CommandsInterface { void setOnIccSmsFull(Handler h, int what, Object obj); void unSetOnIccSmsFull(Handler h); - /** - * Sets the handler for Emergency call-back Mode enter mesage. - * Unlike the register* methods, there's only one notification handler - * - * @param h Handler for notification message. - * @param what User-defined message code. - * @param obj User object. - */ - void setEmergencyCallbackMode(Handler h, int what, Object obj); - /** * Sets the handler for SIM Refresh notifications. * Unlike the register* methods, there's only one notification handler @@ -452,6 +432,49 @@ public interface CommandsInterface { void setSuppServiceNotifications(boolean enable, Message result); //void unSetSuppServiceNotifications(Handler h); + /** + * Sets the handler for Event Notifications for CDMA Display Info. + * Unlike the register* methods, there's only one notification handler + * + * @param h Handler for notification message. + * @param what User-defined message code. + * @param obj User object. + */ + void registerForDisplayInfo(Handler h, int what, Object obj); + void unregisterForDisplayInfo(Handler h); + + /** + * Sets the handler for Event Notifications for CallWaiting Info. + * Unlike the register* methods, there's only one notification handler + * + * @param h Handler for notification message. + * @param what User-defined message code. + * @param obj User object. + */ + void registerForCallWaitingInfo(Handler h, int what, Object obj); + void unregisterForCallWaitingInfo(Handler h); + + /** + * Sets the handler for Event Notifications for Signal Info. + * Unlike the register* methods, there's only one notification handler + * + * @param h Handler for notification message. + * @param what User-defined message code. + * @param obj User object. + */ + void registerForSignalInfo(Handler h, int what, Object obj); + void unregisterForSignalInfo(Handler h); + + /** + * Fires on if Modem enters Emergency Callback mode + */ + void setEmergencyCallbackMode(Handler h, int what, Object obj); + + /** + * Fires on any CDMA OTA provision status change + */ + void registerForCdmaOtaProvision(Handler h,int what, Object obj); + void unregisterForCdmaOtaProvision(Handler h); /** * Returns current ICC status. @@ -867,9 +890,9 @@ public interface CommandsInterface { void setRadioPower(boolean on, Message response); - void acknowledgeLastIncomingSMS(boolean success, Message response); + void acknowledgeLastIncomingGsmSms(boolean success, int cause, Message response); - void acknowledgeLastIncomingCdmaSms(boolean success, Message response); + void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message response); /** * parameters equivilient to 27.007 AT+CRSM command @@ -1072,6 +1095,12 @@ public interface CommandsInterface { */ void setSmscAddress(String address, Message result); + /** + * Indicates whether there is storage available for new SMS messages. + * @param available true if storage is available + * @param result callback message + */ + void reportSmsMemoryStatus(boolean available, Message result); void invokeOemRilRequestRaw(byte[] data, Message response); @@ -1244,7 +1273,9 @@ public interface CommandsInterface { public void getCdmaBroadcastConfig(Message result); /** - * Requests the radio's system selection module to exit emergency callback mode. + * Requests the radio's system selection module to exit emergency callback mode. + * This function should only be called from CDMAPHone.java. + * * @param response callback message */ public void exitEmergencyCallbackMode(Message response); diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java index c6bbf82fd308e..237974d0ce25d 100644 --- a/telephony/java/com/android/internal/telephony/Connection.java +++ b/telephony/java/com/android/internal/telephony/Connection.java @@ -72,6 +72,31 @@ public abstract class Connection { public abstract String getAddress(); + /** + * Gets cdma CNAP name associated with connection + * @return cnap name or null if unavailable + */ + public String getCnapName() { + return null; + } + + /** + * Get orignal dial string + * @return orignal dial string or null if unavailable + */ + public String getOrigDialString(){ + return null; + } + + /** + * Gets cdma CNAP presentation associated with connection + * @return cnap name or null if unavailable + */ + + public int getCnapNamePresentation() { + return 0; + }; + /** * @return Call that owns this Connection, or null if none */ @@ -204,8 +229,14 @@ public abstract class Connection { WILD, /* The post dial string playback is waiting for a call to proceedAfterWildChar() */ COMPLETE, /* The post dial string playback is complete */ - CANCELLED /* The post dial string playback was cancelled + CANCELLED, /* The post dial string playback was cancelled with cancelPostDial() */ + PAUSE /* The post dial string playback is pausing for a + call to processNextPostDialChar*/ + } + + public void clearUserData(){ + userData = null; } public abstract PostDialState getPostDialState(); diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index cc6b452e54c81..6e6f64c160375 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -238,5 +238,10 @@ interface ITelephony { */ String getCdmaEriText(); + /** + * Returns the unread count of voicemails + */ + int getCountVoiceMessages(); + } diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java index 4d0cf41341c4d..260f662452097 100644 --- a/telephony/java/com/android/internal/telephony/Phone.java +++ b/telephony/java/com/android/internal/telephony/Phone.java @@ -102,6 +102,7 @@ public interface Phone { static final String DATA_APN_KEY = "apn"; static final String DATA_IFACE_NAME_KEY = "iface"; static final String NETWORK_UNAVAILABLE_KEY = "networkUnvailable"; + static final String PHONE_IN_ECM_STATE = "phoneinECMState"; /** * APN types for data connections. These are usage categories for an APN @@ -195,6 +196,24 @@ public interface Phone { static final int TTY_MODE_HCO = 2; static final int TTY_MODE_VCO = 3; + /** + * CDMA OTA PROVISION STATUS, the same as RIL_CDMA_OTA_Status in ril.h + */ + + public static final int CDMA_OTA_PROVISION_STATUS_SPL_UNLOCKED = 0; + public static final int CDMA_OTA_PROVISION_STATUS_SPC_RETRIES_EXCEEDED = 1; + public static final int CDMA_OTA_PROVISION_STATUS_A_KEY_EXCHANGED = 2; + public static final int CDMA_OTA_PROVISION_STATUS_SSD_UPDATED = 3; + public static final int CDMA_OTA_PROVISION_STATUS_NAM_DOWNLOADED = 4; + public static final int CDMA_OTA_PROVISION_STATUS_MDN_DOWNLOADED = 5; + public static final int CDMA_OTA_PROVISION_STATUS_IMSI_DOWNLOADED = 6; + public static final int CDMA_OTA_PROVISION_STATUS_PRL_DOWNLOADED = 7; + public static final int CDMA_OTA_PROVISION_STATUS_COMMITTED = 8; + public static final int CDMA_OTA_PROVISION_STATUS_OTAPA_STARTED = 9; + public static final int CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED = 10; + public static final int CDMA_OTA_PROVISION_STATUS_OTAPA_ABORTED = 11; + + /** * Get the current ServiceState. Use * registerForServiceStateChanged to be informed of @@ -273,7 +292,12 @@ public interface Phone { String getActiveApn(); /** - * Get current signal strength. + * Get current signal strength. No change notification available on this + * interface. Use PhoneStateNotifier or an equivalent. + * An ASU is 0-31 or -1 if unknown (for GSM, dBm = -113 - 2 * asu). + * The following special values are defined:

      + *
      • 0 means "-113 dBm or less".
      • + *
      • 31 means "-51 dBm or greater".
      * * @return Current signal strength as SignalStrength */ @@ -499,52 +523,20 @@ public interface Phone { void unregisterForInCallVoicePrivacyOff(Handler h); /** - * Register for notifications about information record available + * Register for notifications when CDMA OTA Provision status change * * @param h Handler that receives the notification message. * @param what User-defined message code. * @param obj User object. */ - void registerCdmaInformationRecord(Handler h, int what, Object obj); + void registerForCdmaOtaStatusChange(Handler h, int what, Object obj); /** - * Unregister for notifications about information record available - * + * Unegister for notifications when CDMA OTA Provision status change * @param h Handler to be removed from the registrant list. */ - void unregisterCdmaInformationRecord(Handler h); + void unregisterForCdmaOtaStatusChange(Handler h); - /** - * Register for the indication of OTA status change - * - * @param h Handler that receives the notification message. - * @param what User-defined message code. - * @param obj User object. - */ - void registerForOtaStatusChange(Handler h, int what, Object obj); - - /** - * Unregister for the indication of OTA status change - * - * @param h Handler to be removed from the registrant list. - */ - void unregisterForOtaStatusChange(Handler h); - - /** - * Register for the indication of Cdma Call Waiting - * - * @param h Handler that receives the notification message. - * @param what User-defined message code. - * @param obj User object. - */ - void registerForCdmaCallWaiting(Handler h, int what, Object obj); - - /** - * Unregister for the indication of Cdma Call Waiting - * - * @param h Handler to be removed from the registrant list. - */ - void unregisterForCdmaCallWaiting(Handler h); /** * Returns SIM record load state. Use * getSimCard().registerForReady() for change notification. @@ -760,9 +752,18 @@ public interface Phone { void stopDtmf(); /** - * Play a Burst of DTMF tone on the active call. Ignored if there is no active call. + * send burst DTMF tone, it can send the string as single character or multiple character + * ignore if there is no active call or not valid digits string. + * Valid digit means only includes characters ISO-LATIN characters 0-9, *, # + * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character, + * this api can send single character and multiple character, also, this api has response + * back to caller. + * + * @param dtmfString is string representing the dialing digit(s) in the active call + * @param onCompelte is the callback message when the action is processed by BP + * */ - void sendBurstDtmf(String dtmfString); + void sendBurstDtmf(String dtmfString, Message onComplete); /** * Sets the radio power on/off state (off is sometimes @@ -826,6 +827,12 @@ public interface Phone { */ String getVoiceMailNumber(); + /** + * Returns unread voicemail count. This count is shown when the voicemail + * notification is expanded.

      + */ + int getCountVoiceMessages(); + /** * Returns the alpha tag associated with the voice mail number. * If there is no alpha tag associated or the record is not yet available, @@ -859,7 +866,7 @@ public interface Phone { * * @param commandInterfaceCFReason is one of the valid call forwarding * CF_REASONS, as defined in - * com.android.internal.telephony.CommandsInterface./code> + * com.android.internal.telephony.CommandsInterface. * @param onComplete a callback message when the action is completed. * @see com.android.internal.telephony.CallForwardInfo for details. */ @@ -872,10 +879,10 @@ public interface Phone { * * @param commandInterfaceCFReason is one of the valid call forwarding * CF_REASONS, as defined in - * com.android.internal.telephony.CommandsInterface./code> + * com.android.internal.telephony.CommandsInterface. * @param commandInterfaceCFAction is one of the valid call forwarding * CF_ACTIONS, as defined in - * com.android.internal.telephony.CommandsInterface./code> + * com.android.internal.telephony.CommandsInterface. * @param dialingNumber is the target phone number to forward calls to * @param timerSeconds is used by CFNRy to indicate the timeout before * forwarding is attempted. @@ -1335,10 +1342,16 @@ public interface Phone { //***** CDMA support methods + /* + * TODO(Moto) TODO(Teleca): can getCdmaMin, getEsn, getMeid use more generic calls + * already defined getXxxx above? + */ + /** * Retrieves the MIN for CDMA phones. */ - String getMin(); + + String getCdmaMin(); /** * Retrieves the ESN for CDMA phones. @@ -1383,14 +1396,6 @@ public interface Phone { */ void queryTTYMode(Message onComplete); - /** - * exitEmergencyCallbackMode - * exits the emergency callback mode - * - * @param onComplete a callback message when the action is completed. - */ - void exitEmergencyCallbackMode(Message onComplete); - /** * Activate or deactivate cell broadcast SMS. * @@ -1438,4 +1443,93 @@ public interface Phone { */ public String getCdmaEriText(); + /** + * request to exit emergency call back mode + * the caller should use setOnECMModeExitResponse + * to receive the emergency callback mode exit response + */ + void exitEmergencyCallbackMode(); + + /** + * this decides if the dial number is OTA(Over the air provision) number or not + * @param dialStr is string representing the dialing digit(s) + * @return true means the dialStr is OTA number, and false means the dialStr is not OTA number + */ + boolean isOtaSpNumber(String dialStr); + + /** + * Register for notifications when CDMA call waiting comes + * + * @param h Handler that receives the notification message. + * @param what User-defined message code. + * @param obj User object. + */ + // TODO(Moto) TODO: Remove when generic implemented + void registerForCallWaiting(Handler h, int what, Object obj); + + /** + * Unegister for notifications when CDMA Call waiting comes + * @param h Handler to be removed from the registrant list. + */ + // TODO(Moto): Remove when generic implemented + void unregisterForCallWaiting(Handler h); + + + /** + * Register for signal information notifications from the network. + * Message.obj will contain an AsyncResult. + * AsyncResult.result will be a SuppServiceNotification instance. + * + * @param h Handler that receives the notification message. + * @param what User-defined message code. + * @param obj User object. + */ + + void registerForSignalInfo(Handler h, int what, Object obj) ; + /** + * Unregisters for signal information notifications. + * Extraneous calls are tolerated silently + * + * @param h Handler to be removed from the registrant list. + */ + void unregisterForSignalInfo(Handler h); + + /** + * Register for display information notifications from the network. + * Message.obj will contain an AsyncResult. + * AsyncResult.result will be a SuppServiceNotification instance. + * + * @param h Handler that receives the notification message. + * @param what User-defined message code. + * @param obj User object. + */ + void registerForDisplayInfo(Handler h, int what, Object obj); + + /** + * Unregisters for display information notifications. + * Extraneous calls are tolerated silently + * + * @param h Handler to be removed from the registrant list. + */ + void unregisterForDisplayInfo(Handler h) ; + + + /** + * registers for exit emergency call back mode request response + * + * @param h Handler that receives the notification message. + * @param what User-defined message code. + * @param obj User object. + */ + + void setOnEcbModeExitResponse(Handler h, int what, Object obj); + + /** + * Unregisters for exit emergency call back mode request response + * + * @param h Handler to be removed from the registrant list. + */ + void unsetOnEcbModeExitResponse(Handler h); + + } diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java index 2849988c3ce4d..ebba09273a8fd 100644 --- a/telephony/java/com/android/internal/telephony/PhoneBase.java +++ b/telephony/java/com/android/internal/telephony/PhoneBase.java @@ -102,8 +102,8 @@ public abstract class PhoneBase implements Phone { protected static final int EVENT_RUIM_RECORDS_LOADED = 21; protected static final int EVENT_NV_READY = 22; protected static final int EVENT_SET_ENHANCED_VP = 23; - protected static final int EVENT_CDMA_CALL_WAITING = 24; - protected static final int EVENT_EMERGENCY_CALLBACK_MODE = 25; + protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER = 24; + protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 25; // Key used to read/write current CLIR setting public static final String CLIR_KEY = "clir_key"; @@ -296,36 +296,6 @@ public abstract class PhoneBase implements Phone { mCM.unregisterForInCallVoicePrivacyOff(h); } - // Inherited documentation suffices. - public void registerForOtaStatusChange(Handler h, int what, Object obj){ - mCM.registerForOtaSessionStatus(h,what,obj); - } - - // Inherited documentation suffices. - public void unregisterForOtaStatusChange(Handler h){ - mCM.unregisterForOtaSessionStatus(h); - } - - // Inherited documentation suffices. - public void registerCdmaInformationRecord(Handler h, int what, Object obj){ - mCM.registerCdmaInformationRecord(h,what,obj); - } - - // Inherited documentation suffices. - public void unregisterCdmaInformationRecord(Handler h){ - mCM.unregisterCdmaInformationRecord(h); - } - - // Inherited documentation suffices. - public void registerForCdmaCallWaiting(Handler h, int what, Object obj){ - mCM.registerForCdmaCallWaiting(h,what,obj); - } - - // Inherited documentation suffices. - public void unregisterForCdmaCallWaiting(Handler h){ - mCM.unregisterForCdmaCallWaiting(h); - } - /** * Notifiy registrants of a new ringing Connection. * Subclasses of Phone probably want to replace this with a @@ -650,14 +620,6 @@ public abstract class PhoneBase implements Phone { Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); } - /** - * Send the exit emergency callback mode message - */ - public void exitEmergencyCallbackMode(Message onComplete) { - // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. - Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); - } - /** * This should only be called in GSM mode. * Only here for some backward compatibility @@ -704,6 +666,11 @@ public abstract class PhoneBase implements Phone { public abstract String getPhoneName(); + /** @hide */ + public int getCountVoiceMessages(){ + return 0; + } + /** * Returns the CDMA ERI icon index to display */ @@ -730,4 +697,71 @@ public abstract class PhoneBase implements Phone { return "GSM nw, no ERI"; } + public String getCdmaMin() { + // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. + Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); + return null; + } + + public void sendBurstDtmf(String dtmfString, Message onComplete) { + // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. + Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); + } + + public void exitEmergencyCallbackMode() { + // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. + Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); + } + + public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) { + // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. + Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); + } + + public void unregisterForCdmaOtaStatusChange(Handler h) { + // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. + Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); + } + + public boolean isOtaSpNumber(String dialStr) { + // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. + Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); + return false; + } + + public void registerForCallWaiting(Handler h, int what, Object obj){ + // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. + Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); + } + + public void unregisterForCallWaiting(Handler h){ + // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. + Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); + } + + public void registerForSignalInfo(Handler h, int what, Object obj) { + mCM.registerForSignalInfo(h, what, obj); + } + + public void unregisterForSignalInfo(Handler h) { + mCM.unregisterForSignalInfo(h); + } + + public void registerForDisplayInfo(Handler h, int what, Object obj) { + mCM.registerForDisplayInfo(h, what, obj); + } + + public void unregisterForDisplayInfo(Handler h) { + mCM.unregisterForDisplayInfo(h); + } + + public void setOnEcbModeExitResponse(Handler h, int what, Object obj){ + // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. + Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); + } + + public void unsetOnEcbModeExitResponse(Handler h){ + // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. + Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); + } } diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java index a329cbbaac2c1..7d968f97e5e06 100644 --- a/telephony/java/com/android/internal/telephony/PhoneProxy.java +++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java @@ -306,28 +306,12 @@ public class PhoneProxy extends Handler implements Phone { mActivePhone.unregisterForInCallVoicePrivacyOff(h); } - public void registerCdmaInformationRecord(Handler h, int what, Object obj) { - mActivePhone.registerCdmaInformationRecord(h,what,obj); + public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) { + mActivePhone.registerForCdmaOtaStatusChange(h,what,obj); } - public void unregisterCdmaInformationRecord(Handler h) { - mActivePhone.unregisterCdmaInformationRecord(h); - } - - public void registerForOtaStatusChange(Handler h, int what, Object obj){ - mActivePhone.registerForOtaStatusChange(h,what,obj); - } - - public void unregisterForOtaStatusChange(Handler h){ - mActivePhone.unregisterForOtaStatusChange(h); - } - - public void registerForCdmaCallWaiting(Handler h, int what, Object obj){ - mActivePhone.registerForCdmaCallWaiting(h,what,obj); - } - - public void unregisterForCdmaCallWaiting(Handler h){ - mActivePhone.unregisterForCdmaCallWaiting(h); + public void unregisterForCdmaOtaStatusChange(Handler h) { + mActivePhone.unregisterForCdmaOtaStatusChange(h); } public boolean getIccRecordsLoaded() { @@ -414,10 +398,6 @@ public class PhoneProxy extends Handler implements Phone { mActivePhone.stopDtmf(); } - public void sendBurstDtmf(String dtmfString) { - mActivePhone.sendBurstDtmf(dtmfString); - } - public void setRadioPower(boolean power) { mActivePhone.setRadioPower(power); } @@ -434,6 +414,10 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.getLine1Number(); } + public String getCdmaMin() { + return mActivePhone.getCdmaMin(); + } + public String getLine1AlphaTag() { return mActivePhone.getLine1AlphaTag(); } @@ -446,6 +430,11 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.getVoiceMailNumber(); } + /** @hide */ + public int getCountVoiceMessages(){ + return mActivePhone.getCountVoiceMessages(); + } + public String getVoiceMailAlphaTag() { return mActivePhone.getVoiceMailAlphaTag(); } @@ -656,10 +645,6 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.getIccSerialNumber(); } - public String getMin() { - return mActivePhone.getMin(); - } - public String getEsn() { return mActivePhone.getEsn(); } @@ -688,10 +673,6 @@ public class PhoneProxy extends Handler implements Phone { mActivePhone.queryTTYMode(onComplete); } - public void exitEmergencyCallbackMode(Message onComplete) { - mActivePhone.exitEmergencyCallbackMode(onComplete); - } - public void activateCellBroadcastSms(int activate, Message response) { mActivePhone.activateCellBroadcastSms(activate, response); } @@ -720,12 +701,55 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.getCdmaEriIconIndex(); } + public String getCdmaEriText() { + return mActivePhone.getCdmaEriText(); + } + public int getCdmaEriIconMode() { return mActivePhone.getCdmaEriIconMode(); } - public String getCdmaEriText() { - return mActivePhone.getCdmaEriText(); + public void sendBurstDtmf(String dtmfString, Message onComplete){ + mActivePhone.sendBurstDtmf(dtmfString,onComplete); + } + + public void exitEmergencyCallbackMode(){ + mActivePhone.exitEmergencyCallbackMode(); + } + + public boolean isOtaSpNumber(String dialStr){ + return mActivePhone.isOtaSpNumber(dialStr); + } + + public void registerForCallWaiting(Handler h, int what, Object obj){ + mActivePhone.registerForCallWaiting(h,what,obj); + } + + public void unregisterForCallWaiting(Handler h){ + mActivePhone.unregisterForCallWaiting(h); + } + + public void registerForSignalInfo(Handler h, int what, Object obj) { + mActivePhone.registerForSignalInfo(h,what,obj); + } + + public void unregisterForSignalInfo(Handler h) { + mActivePhone.unregisterForSignalInfo(h); + } + + public void registerForDisplayInfo(Handler h, int what, Object obj) { + mActivePhone.registerForDisplayInfo(h,what,obj); + } + + public void unregisterForDisplayInfo(Handler h) { + mActivePhone.unregisterForDisplayInfo(h); + } + + public void setOnEcbModeExitResponse(Handler h, int what, Object obj){ + mActivePhone.setOnEcbModeExitResponse(h,what,obj); + } + + public void unsetOnEcbModeExitResponse(Handler h){ + mActivePhone.unsetOnEcbModeExitResponse(h); } } - diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java index 070d233bbdb66..ea84b09801e45 100644 --- a/telephony/java/com/android/internal/telephony/RIL.java +++ b/telephony/java/com/android/internal/telephony/RIL.java @@ -38,11 +38,18 @@ import android.telephony.SmsMessage; import android.util.Config; import android.util.Log; -import com.android.internal.telephony.CdmaInformationRecord; -import com.android.internal.telephony.cdma.CdmaCallWaiting; +import com.android.internal.telephony.CallForwardInfo; +import com.android.internal.telephony.CommandException; import com.android.internal.telephony.DataCallState; import com.android.internal.telephony.gsm.NetworkInfo; import com.android.internal.telephony.gsm.SuppServiceNotification; +import com.android.internal.telephony.IccCardApplication; +import com.android.internal.telephony.IccCardStatus; +import com.android.internal.telephony.IccUtils; +import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.SmsResponse; +import com.android.internal.telephony.cdma.CdmaCallWaitingNotification; +import com.android.internal.telephony.cdma.CdmaInformationRecords; import java.io.ByteArrayInputStream; import java.io.DataInputStream; @@ -1063,10 +1070,11 @@ public final class RIL extends BaseCommands implements CommandsInterface { sendBurstDtmf(String dtmfString, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_BURST_DTMF, result); - if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); - rr.mp.writeString(dtmfString); + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " : " + dtmfString); + send(rr); } @@ -1331,28 +1339,32 @@ public final class RIL extends BaseCommands implements CommandsInterface { } public void - acknowledgeLastIncomingSMS(boolean success, Message result) { + acknowledgeLastIncomingGsmSms(boolean success, int cause, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_SMS_ACKNOWLEDGE, result); - rr.mp.writeInt(1); + rr.mp.writeInt(2); rr.mp.writeInt(success ? 1 : 0); + rr.mp.writeInt(cause); - if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + success + " " + cause); send(rr); } public void - acknowledgeLastIncomingCdmaSms(boolean success, Message result) { + acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE, result); + rr.mp.writeInt(2); rr.mp.writeInt(success ? 0 : 1); //RIL_CDMA_SMS_ErrorClass // cause code according to X.S004-550E - rr.mp.writeInt(39); //39 means other terminal problem; is not interpreted for success. + rr.mp.writeInt(cause); - if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + success + " " + cause); send(rr); } @@ -1804,6 +1816,20 @@ public final class RIL extends BaseCommands implements CommandsInterface { send(rr); } + /** + * {@inheritDoc} + */ + public void reportSmsMemoryStatus(boolean available, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_REPORT_SMS_MEMORY_STATUS, result); + rr.mp.writeInt(1); + rr.mp.writeInt(available ? 1 : 0); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + + requestToString(rr.mRequest) + ": " + available); + + send(rr); + } + //***** Private Methods private void sendScreenState(boolean on) { @@ -1992,7 +2018,7 @@ public final class RIL extends BaseCommands implements CommandsInterface { case RIL_REQUEST_CONFERENCE: ret = responseVoid(p); break; case RIL_REQUEST_UDUB: ret = responseVoid(p); break; case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: ret = responseInts(p); break; - case RIL_REQUEST_SIGNAL_STRENGTH: ret = responseInts(p); break; + case RIL_REQUEST_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break; case RIL_REQUEST_REGISTRATION_STATE: ret = responseStrings(p); break; case RIL_REQUEST_GPRS_REGISTRATION_STATE: ret = responseStrings(p); break; case RIL_REQUEST_OPERATOR: ret = responseStrings(p); break; @@ -2187,7 +2213,7 @@ public final class RIL extends BaseCommands implements CommandsInterface { case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: ret = responseInts(p); break; case RIL_UNSOL_ON_USSD: ret = responseStrings(p); break; case RIL_UNSOL_NITZ_TIME_RECEIVED: ret = responseString(p); break; - case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseInts(p); break; + case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break; case RIL_UNSOL_DATA_CALL_LIST_CHANGED: ret = responseDataCallList(p);break; case RIL_UNSOL_SUPP_SVC_NOTIFICATION: ret = responseSuppServiceNotification(p); break; case RIL_UNSOL_STK_SESSION_END: ret = responseVoid(p); break; @@ -2205,7 +2231,7 @@ public final class RIL extends BaseCommands implements CommandsInterface { case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break; case RIL_UNSOL_CDMA_CALL_WAITING: ret = responseCdmaCallWaiting(p); break; case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: ret = responseInts(p); break; - case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break; + case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInfoRec(p); break; case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break; default: @@ -2391,10 +2417,11 @@ public final class RIL extends BaseCommands implements CommandsInterface { break; case RIL_UNSOL_CALL_RING: - if (RILJ_LOGD) unsljLog(response); + if (RILJ_LOGD) unsljLogRet(response, ret); if (mRingRegistrant != null) { - mRingRegistrant.notifyRegistrant(); + mRingRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); } break; @@ -2434,13 +2461,6 @@ public final class RIL extends BaseCommands implements CommandsInterface { } break; - case RIL_UNSOL_OEM_HOOK_RAW: - if (RILJ_LOGD) unsljLogvRet(response, IccUtils.bytesToHexString((byte[])ret)); - if (mUnsolOemHookRawRegistrant != null) { - mUnsolOemHookRawRegistrant.notifyRegistrant(new AsyncResult(null, ret, null)); - } - break; - case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: if (RILJ_LOGD) unsljLog(response); @@ -2452,25 +2472,46 @@ public final class RIL extends BaseCommands implements CommandsInterface { case RIL_UNSOL_CDMA_CALL_WAITING: if (RILJ_LOGD) unsljLog(response); - if(mCallWaitingRegistrants != null) { - mCallWaitingRegistrants.notifyRegistrants(new AsyncResult (null, ret, null)); + if (mCallWaitingInfoRegistrants != null) { + mCallWaitingInfoRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); } break; case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: - if (RILJ_LOGD) unsljLog(response); + if (RILJ_LOGD) unsljLogRet(response, ret); - if (mOtaSessionRegistrants != null) { - mOtaSessionRegistrants.notifyRegistrants(new AsyncResult(null, ret, null)); + if (mOtaProvisionRegistrants != null) { + mOtaProvisionRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); } break; case RIL_UNSOL_CDMA_INFO_REC: - if (RILJ_LOGD) - unsljLog(response); - if (mInformationRecordsRegistrants != null) { - mInformationRecordsRegistrants.notifyRegistrants(new AsyncResult(null, ret, - null)); + if (RILJ_LOGD) unsljLog(response); + + CdmaInformationRecords infoRec = (CdmaInformationRecords) ret; + if (infoRec.isDispInfo) { + if (mDisplayInfoRegistrants != null) { + if (RILJ_LOGD) unsljLogRet(response, infoRec.cdmaDisplayInfoRecord); + + mDisplayInfoRegistrants.notifyRegistrants( + new AsyncResult (null, infoRec.cdmaDisplayInfoRecord, null)); + } + } + if (infoRec.isSignInfo) { + if (mSignalInfoRegistrants != null) { + if (RILJ_LOGD) unsljLogRet(response, infoRec.cdmaSignalInfoRecord); + mSignalInfoRegistrants.notifyRegistrants( + new AsyncResult (null, infoRec.cdmaSignalInfoRecord, null)); + } + } + break; + + case RIL_UNSOL_OEM_HOOK_RAW: + if (RILJ_LOGD) unsljLogvRet(response, IccUtils.bytesToHexString((byte[])ret)); + if (mUnsolOemHookRawRegistrant != null) { + mUnsolOemHookRawRegistrant.notifyRegistrant(new AsyncResult(null, ret, null)); } break; } @@ -2721,11 +2762,8 @@ public final class RIL extends BaseCommands implements CommandsInterface { dc.als = p.readInt(); voiceSettings = p.readInt(); dc.isVoice = (0 == voiceSettings) ? false : true; - - //dc.isVoicePrivacy = (0 != p.readInt()); int voicePrivacy = p.readInt(); dc.isVoicePrivacy = (0 != voicePrivacy); - dc.number = p.readString(); int np = p.readInt(); dc.numberPresentation = DriverCall.presentationFromCLIP(np); @@ -2834,15 +2872,48 @@ public final class RIL extends BaseCommands implements CommandsInterface { private Object responseCDMA_BR_CNF(Parcel p) { - int numInts; + int numServiceCategories; int response[]; - numInts = p.readInt(); + numServiceCategories = p.readInt(); + if (numServiceCategories == 0) { + int numInts; + numInts = CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES * CDMA_BSI_NO_OF_INTS_STRUCT + 1; + response = new int[numInts]; + + // Indicate that a zero length table was received + response[0] = 0; // TODO(Moto): This is very strange, please explain why. + + // Loop over CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES set 'english' as + // default language and selection status to false + for (int i = 1; i < numInts; i += CDMA_BSI_NO_OF_INTS_STRUCT ) { + response[i + 0] = i / CDMA_BSI_NO_OF_INTS_STRUCT; + response[i + 1] = 1; + response[i + 2] = 0; + } + } else { + int numInts; + numInts = (numServiceCategories * CDMA_BSI_NO_OF_INTS_STRUCT) + 1; + response = new int[numInts]; + + response[0] = numServiceCategories; + for (int i = 1 ; i < numInts; i++) { + response[i] = p.readInt(); + } + } + + return response; + } + + private Object + responseSignalStrength(Parcel p) { + int numInts = 7; + int response[]; + + /* TODO: Add SignalStrength class to match RIL_SignalStrength */ response = new int[numInts]; - - response[0] = numInts; - for (int i = 1 ; i < numInts; i++) { + for (int i = 0 ; i < numInts ; i++) { response[i] = p.readInt(); } @@ -2850,105 +2921,81 @@ public final class RIL extends BaseCommands implements CommandsInterface { } private Object - responseCdmaInformationRecord(Parcel p){ + responseCdmaInfoRec(Parcel p) { + int infoRecordName; + CdmaInformationRecords records = new CdmaInformationRecords(); - int num; - ArrayList response; - - num = p.readInt(); - - response = new ArrayList(num); - - for (int i = 0; i < num; i++) { - int name = p.readInt(); - CdmaInformationRecord InfoRec = new CdmaInformationRecord(name); - - char buffer[]; - int length; - switch (name) { - case CdmaInformationRecord.RIL_CDMA_DISPLAY_INFO_REC: - case CdmaInformationRecord.RIL_CDMA_EXTENDED_DISPLAY_INFO_REC: - length = p.readInt(); - buffer = new char[length]; - for (int j = 0; j < length; j++) { - buffer[j] = (char)p.readInt(); - } - InfoRec.createDisplayInfo(length, buffer); + int numberOfInfoRecs = p.readInt(); + for (int i = 0; i < numberOfInfoRecs; i++) { + infoRecordName = p.readInt(); + switch(infoRecordName) { + case CdmaInformationRecords.RIL_CDMA_DISPLAY_INFO_REC: + case CdmaInformationRecords.RIL_CDMA_EXTENDED_DISPLAY_INFO_REC: + records.setDispInfo(p.readString()); break; - - case CdmaInformationRecord.RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC: - case CdmaInformationRecord.RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC: - case CdmaInformationRecord.RIL_CDMA_CONNECTED_NUMBER_INFO_REC: - length = p.readInt(); - buffer = new char[length + 4]; - for (int j = 0; j < (length + 4); j++) { - buffer[j] = (char)p.readInt(); - } - InfoRec.createNumberInfo(length, buffer); + case CdmaInformationRecords.RIL_CDMA_SIGNAL_INFO_REC: + records.setSignInfo(p.readInt(), p.readInt(), p.readInt(), p.readInt()); break; - - case CdmaInformationRecord.RIL_CDMA_SIGNAL_INFO_REC: - buffer = new char[4]; - for (int j = 0; j < 4; j++) { - buffer[j] = (char)p.readInt(); - } - InfoRec.createSignalInfo(buffer); + // InfoReocords with names as below aren't supported in AFW yet + case CdmaInformationRecords.RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC: + case CdmaInformationRecords.RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC: + case CdmaInformationRecords.RIL_CDMA_CONNECTED_NUMBER_INFO_REC: + // TODO(Moto) implement + p.readString(); // number + p.readInt(); // number_type + p.readInt(); // number_plan + p.readInt(); // pi + p.readInt(); // si break; - - case CdmaInformationRecord.RIL_CDMA_REDIRECTING_NUMBER_INFO_REC: - length = p.readInt(); - buffer = new char[length + 4]; - int reason; - for (int j = 0; j < (length + 4); j++) { - buffer[j] = (char)p.readInt(); - } - reason = p.readInt(); - InfoRec.createRedirectingNumberInfo(length, buffer, reason); + case CdmaInformationRecords.RIL_CDMA_REDIRECTING_NUMBER_INFO_REC: + // TODO(Moto) implement + p.readString(); // redirecting number + p.readInt(); // number_type + p.readInt(); // number_plan + p.readInt(); // pi + p.readInt(); // si + p.readInt(); // reason break; - - case CdmaInformationRecord.RIL_CDMA_LINE_CONTROL_INFO_REC: - buffer = new char[4]; - for (int j = 0; j < 4; j++) { - buffer[j] = (char)p.readInt(); - } - InfoRec.createLineControlInfo(buffer); + case CdmaInformationRecords.RIL_CDMA_LINE_CONTROL_INFO_REC: + // TODO(Moto) implement + p.readInt(); // PolarityIncluded + p.readInt(); // Toggle + p.readInt(); // Reverse + p.readInt(); // PowerDenial break; - - case CdmaInformationRecord.RIL_CDMA_T53_CLIR_INFO_REC: - char ch = (char)p.readInt(); - InfoRec.createT53ClirInfo(ch); + case CdmaInformationRecords.RIL_CDMA_T53_CLIR_INFO_REC: + // TODO(Moto) implement + p.readInt(); // Cause break; - - case CdmaInformationRecord.RIL_CDMA_T53_RELEASE_INFO_REC: + case CdmaInformationRecords.RIL_CDMA_T53_AUDIO_CONTROL_INFO_REC: + // TODO(Moto) implement + p.readInt(); // upLink + p.readInt(); // downLink break; - - case CdmaInformationRecord.RIL_CDMA_T53_AUDIO_CONTROL_INFO_REC: - char ul = (char)p.readInt(); - char dl = (char)p.readInt(); - InfoRec.createT53AudioControlInfo(ul, dl); - break; - + case CdmaInformationRecords.RIL_CDMA_T53_RELEASE_INFO_REC: + // TODO(Moto) implement unknown fall through default: - break; + throw new RuntimeException("RIL_UNSOL_CDMA_INFO_REC: unsupported record. Got " + + records.recordToString(infoRecordName) + " "); } - response.add(InfoRec); } - - return response; + return records; } private Object - responseCdmaCallWaiting(Parcel p){ - CdmaCallWaiting response = new CdmaCallWaiting(); - response.number = p.readString(); - response.numberPresentation = p.readInt(); - response.name = p.readString(); - response.signalInfoRecord.isPresent = p.readInt() == 0 ? false : true; - response.signalInfoRecord.signalType = p.readInt(); - response.signalInfoRecord.alertPitch = p.readInt(); - response.signalInfoRecord.signalCode = p.readInt(); + responseCdmaCallWaiting(Parcel p) { + CdmaCallWaitingNotification notification = new CdmaCallWaitingNotification(); - return response; + notification.number = p.readString(); + notification.numberPresentation = p.readInt(); + notification.name = p.readString(); + notification.namePresentation = notification.numberPresentation; + notification.isPresent = p.readInt(); + notification.signalType = p.readInt(); + notification.alertPitch = p.readInt(); + notification.signal = p.readInt(); + + return notification; } private Object @@ -3104,16 +3151,16 @@ public final class RIL extends BaseCommands implements CommandsInterface { case RIL_UNSOL_SIM_SMS_STORAGE_FULL: return "UNSOL_SIM_SMS_STORAGE_FULL"; case RIL_UNSOL_SIM_REFRESH: return "UNSOL_SIM_REFRESH"; case RIL_UNSOL_CALL_RING: return "UNSOL_CALL_RING"; - case RIL_UNSOL_RESTRICTED_STATE_CHANGED: return "RIL_UNSOL_RESTRICTED_STATE_CHANGED"; - case RIL_UNSOL_OEM_HOOK_RAW: return "RIL_UNSOL_OEM_HOOK_RAW"; case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: return "UNSOL_RESPONSE_SIM_STATUS_CHANGED"; case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: return "UNSOL_RESPONSE_CDMA_NEW_SMS"; case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: return "UNSOL_RESPONSE_NEW_BROADCAST_SMS"; case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: return "UNSOL_CDMA_RUIM_SMS_STORAGE_FULL"; + case RIL_UNSOL_RESTRICTED_STATE_CHANGED: return "UNSOL_RESTRICTED_STATE_CHANGED"; case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: return "UNSOL_ENTER_EMERGENCY_CALLBACK_MODE"; case RIL_UNSOL_CDMA_CALL_WAITING: return "UNSOL_CDMA_CALL_WAITING"; case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: return "UNSOL_CDMA_OTA_PROVISION_STATUS"; case RIL_UNSOL_CDMA_INFO_REC: return "UNSOL_CDMA_INFO_REC"; + case RIL_UNSOL_OEM_HOOK_RAW: return "UNSOL_OEM_HOOK_RAW"; default: return ""; } } @@ -3286,8 +3333,7 @@ public final class RIL extends BaseCommands implements CommandsInterface { * {@inheritDoc} */ public void exitEmergencyCallbackMode(Message response) { - RILRequest rr - = RILRequest.obtain(RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, response); + RILRequest rr = RILRequest.obtain(RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, response); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 44c863b90aead..26995ef240620 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -222,6 +222,7 @@ cat include/telephony/ril.h | \ int RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE = 99; int RIL_REQUEST_GET_SMSC_ADDRESS = 100; int RIL_REQUEST_SET_SMSC_ADDRESS = 101; + int RIL_REQUEST_REPORT_SMS_MEMORY_STATUS = 102; int RIL_UNSOL_RESPONSE_BASE = 1000; int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000; int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001; diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java index d055c3114f1ff..12808ceacd364 100644 --- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java @@ -20,6 +20,7 @@ import android.app.Activity; import android.app.PendingIntent; import android.app.AlertDialog; import android.app.PendingIntent.CanceledException; +import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; @@ -32,6 +33,7 @@ import android.net.Uri; import android.os.AsyncResult; import android.os.Handler; import android.os.Message; +import android.os.PowerManager; import android.provider.Telephony; import android.provider.Telephony.Sms.Intents; import android.provider.Settings; @@ -128,6 +130,15 @@ public abstract class SMSDispatcher extends Handler { private SmsTracker mSTracker; + /** Wake lock to ensure device stays awake while dispatching the SMS intent. */ + private PowerManager.WakeLock mWakeLock; + + /** + * Hold the wake lock for 5 seconds, which should be enough time for + * any receiver(s) to grab its own wake lock. + */ + private final int WAKE_LOCK_TIMEOUT = 5000; + private static SmsMessage mSmsMessage; private static SmsMessageBase mSmsMessageBase; private SmsMessageBase.SubmitPduBase mSubmitPduBase; @@ -196,14 +207,16 @@ public abstract class SMSDispatcher extends Handler { protected SMSDispatcher(PhoneBase phone) { mPhone = phone; - mWapPush = new WapPushOverSms(phone); + mWapPush = new WapPushOverSms(phone, this); mContext = phone.getContext(); mResolver = mContext.getContentResolver(); mCm = phone.mCM; mSTracker = null; + createWakelock(); + int check_period = Settings.Gservices.getInt(mResolver, - Settings.Gservices.SMS_OUTGOING_CEHCK_INTERVAL_MS, + Settings.Gservices.SMS_OUTGOING_CHECK_INTERVAL_MS, DEFAULT_SMS_CHECK_PERIOD); int max_count = Settings.Gservices.getInt(mResolver, Settings.Gservices.SMS_OUTGOING_CEHCK_MAX_COUNT, @@ -257,16 +270,17 @@ public abstract class SMSDispatcher extends Handler { ar = (AsyncResult) msg.obj; - // FIXME only acknowledge on store - acknowledgeLastIncomingSms(true, null); - if (ar.exception != null) { Log.e(TAG, "Exception processing incoming SMS. Exception:" + ar.exception); return; } sms = (SmsMessage) ar.result; - dispatchMessage(sms.mWrappedSmsMessage); + try { + dispatchMessage(sms.mWrappedSmsMessage); + } catch (RuntimeException ex) { + acknowledgeLastIncomingSms(false, Intents.RESULT_SMS_GENERIC_ERROR, null); + } break; @@ -310,6 +324,28 @@ public abstract class SMSDispatcher extends Handler { } } + private void createWakelock() { + PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); + mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SMSDispatcher"); + mWakeLock.setReferenceCounted(true); + } + + /** + * Grabs a wake lock and sends intent as an ordered broadcast. + * The resultReceiver will check for errors and ACK/NACK back + * to the RIL. + * + * @param intent intent to broadcast + * @param permission Receivers are required to have this permission + */ + void dispatch(Intent intent, String permission) { + // Hold a wake lock for WAKE_LOCK_TIMEOUT seconds, enough to give any + // receivers time to take their own wake locks. + mWakeLock.acquire(WAKE_LOCK_TIMEOUT); + mContext.sendOrderedBroadcast(intent, permission, mResultReceiver, + this, Activity.RESULT_OK, null, null); + } + /** * Called when SIM_FULL message is received from the RIL. Notifies interested * parties that SIM storage for SMS messages is full. @@ -317,7 +353,8 @@ public abstract class SMSDispatcher extends Handler { private void handleIccFull(){ // broadcast SIM_FULL intent Intent intent = new Intent(Intents.SIM_FULL_ACTION); - mPhone.getContext().sendBroadcast(intent, "android.permission.RECEIVE_SMS"); + mWakeLock.acquire(WAKE_LOCK_TIMEOUT); + mContext.sendBroadcast(intent, "android.permission.RECEIVE_SMS"); } /** @@ -454,6 +491,7 @@ public abstract class SMSDispatcher extends Handler { values.put("destination_port", portAddrs.destPort); } mResolver.insert(mRawUri, values); + acknowledgeLastIncomingSms(true, Intents.RESULT_SMS_HANDLED, null); return; } @@ -475,7 +513,9 @@ public abstract class SMSDispatcher extends Handler { mResolver.delete(mRawUri, where.toString(), whereArgs); } catch (SQLException e) { Log.e(TAG, "Can't access multipart SMS database", e); - return; // TODO: NACK the message or something, don't just discard. + // TODO: Would OUT_OF_MEMORY be more appropriate? + acknowledgeLastIncomingSms(false, Intents.RESULT_SMS_GENERIC_ERROR, null); + return; } finally { if (cursor != null) cursor.close(); } @@ -519,8 +559,7 @@ public abstract class SMSDispatcher extends Handler { protected void dispatchPdus(byte[][] pdus) { Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION); intent.putExtra("pdus", pdus); - mPhone.getContext().sendBroadcast( - intent, "android.permission.RECEIVE_SMS"); + dispatch(intent, "android.permission.RECEIVE_SMS"); } /** @@ -533,8 +572,7 @@ public abstract class SMSDispatcher extends Handler { Uri uri = Uri.parse("sms://localhost:" + port); Intent intent = new Intent(Intents.DATA_SMS_RECEIVED_ACTION, uri); intent.putExtra("pdus", pdus); - mPhone.getContext().sendBroadcast( - intent, "android.permission.RECEIVE_SMS"); + dispatch(intent, "android.permission.RECEIVE_SMS"); } @@ -698,9 +736,11 @@ public abstract class SMSDispatcher extends Handler { /** * Send an acknowledge message. * @param success indicates that last message was successfully received. + * @param result result code indicating any error * @param response callback message sent when operation completes. */ - protected abstract void acknowledgeLastIncomingSms(boolean success, Message response); + protected abstract void acknowledgeLastIncomingSms(boolean success, + int result, Message response); /** * Check if a SmsTracker holds multi-part Sms @@ -751,4 +791,17 @@ public abstract class SMSDispatcher extends Handler { } } }; + + private BroadcastReceiver mResultReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int rc = getResultCode(); + boolean success = (rc == Activity.RESULT_OK) || (rc == Intents.RESULT_SMS_HANDLED); + + // For a multi-part message, this only ACKs the last part. + // Previous parts were ACK'd as they were received. + acknowledgeLastIncomingSms(success, rc, null); + } + + }; } diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java index 91aa34e79b232..c78ceaec49601 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java +++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java @@ -54,8 +54,10 @@ public class TelephonyIntents { public static final String ACTION_RADIO_TECHNOLOGY_CHANGED = "android.intent.action.RADIO_TECHNOLOGY"; /** - *

      Broadcast Action: The emergency callback mode is entered. - * + *

      Broadcast Action: The emergency callback mode is changed. + *

        + *
      • phoneinECMState - A boolean value,true=phone in ECM, false=ECM off
      • + *
      *

      * You can not receive this through components declared * in manifests, only by explicitly registering for it with @@ -65,8 +67,8 @@ public class TelephonyIntents { *

      * Requires no permission. */ - public static final String ACTION_EMERGENCY_CALLBACK_MODE_ENTERED - = "android.intent.action.EMERGENCY_CALLBACK_MODE"; + public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED + = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED"; /** * Broadcast Action: The phone's signal strength has changed. The intent will have the * following extra values:

      @@ -179,4 +181,28 @@ public class TelephonyIntents { */ public static final String ACTION_NETWORK_SET_TIMEZONE = "android.intent.action.NETWORK_SET_TIMEZONE"; + + /** + *

      Broadcast Action: It indicates the Emergency callback mode blocks datacall/sms + *

      . + */ + // TODO(Moto): What is the use case, who is interested in this? + public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS + = "android.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS"; + + /** + * Broadcast Action: The MDN changed during the CDMA OTA Process + * The intent will have the following extra values:

      + *
        + *
      • mdn - An Integer of the updated MDN number.
      • + *
      + * + *

      + */ + // TODO(Moto): Generally broadcast intents are for use to allow entities which + // may not know about each other to "communicate". This seems quite specific + // and maybe using the registrant style would be better. + public static final String ACTION_CDMA_OTA_MDN_CHANGED + = "android.intent.action.ACTION_MDN_STATE_CHANGED"; + } diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index 453185f89bd97..4e8950fe1effa 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -98,4 +98,7 @@ public interface TelephonyProperties */ static String PROPERTY_DATA_NETWORK_TYPE = "gsm.network.type"; + /** Indicate if phone is in emergency callback mode */ + static final String PROPERTY_INECM_MODE = "ril.cdma.inecmmode"; + } diff --git a/telephony/java/com/android/internal/telephony/WapPushOverSms.java b/telephony/java/com/android/internal/telephony/WapPushOverSms.java index 98899c903684e..c851bc1b0fde3 100644 --- a/telephony/java/com/android/internal/telephony/WapPushOverSms.java +++ b/telephony/java/com/android/internal/telephony/WapPushOverSms.java @@ -18,7 +18,6 @@ package com.android.internal.telephony; import android.content.Context; import android.content.Intent; -import android.os.PowerManager; import android.provider.Telephony.Sms.Intents; import android.util.Config; import android.util.Log; @@ -34,7 +33,7 @@ public class WapPushOverSms { private final Context mContext; private WspTypeDecoder pduDecoder; - private PowerManager.WakeLock mWakeLock; + private SMSDispatcher mSmsDispatcher; /** * Hold the wake lock for 5 seconds, which should be enough time for @@ -42,10 +41,9 @@ public class WapPushOverSms { */ private final int WAKE_LOCK_TIMEOUT = 5000; - public WapPushOverSms(Phone phone) { - + public WapPushOverSms(Phone phone, SMSDispatcher smsDispatcher) { + mSmsDispatcher = smsDispatcher; mContext = phone.getContext(); - createWakelock(); } /** @@ -184,7 +182,7 @@ public class WapPushOverSms { intent.putExtra("pduType", pduType); intent.putExtra("data", data); - sendBroadcast(intent, "android.permission.RECEIVE_WAP_PUSH"); + mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_WAP_PUSH"); } private void dispatchWapPdu_PushCO(byte[] pdu, int transactionId, int pduType) { @@ -194,7 +192,7 @@ public class WapPushOverSms { intent.putExtra("pduType", pduType); intent.putExtra("data", pdu); - sendBroadcast(intent, "android.permission.RECEIVE_WAP_PUSH"); + mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_WAP_PUSH"); } private void dispatchWapPdu_MMS(byte[] pdu, int transactionId, int pduType, int dataIndex) { @@ -209,20 +207,7 @@ public class WapPushOverSms { intent.putExtra("pduType", pduType); intent.putExtra("data", data); - sendBroadcast(intent, "android.permission.RECEIVE_MMS"); - } - - private void createWakelock() { - PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); - mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WapPushOverSms"); - mWakeLock.setReferenceCounted(true); - } - - private void sendBroadcast(Intent intent, String permission) { - // Hold a wake lock for WAKE_LOCK_TIMEOUT seconds, enough to give any - // receivers time to take their own wake locks. - mWakeLock.acquire(WAKE_LOCK_TIMEOUT); - mContext.sendBroadcast(intent, permission); + mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_MMS"); } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index 03f7f986da057..c0bfe5e6fd343 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -35,6 +35,7 @@ import android.text.TextUtils; import android.util.Log; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_BASEBAND_VERSION; +import static com.android.internal.telephony.TelephonyProperties.PROPERTY_INECM_MODE; import com.android.internal.telephony.CallStateException; import com.android.internal.telephony.CommandsInterface; @@ -54,9 +55,9 @@ import com.android.internal.telephony.RILConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyProperties; -import java.util.ArrayList; import java.util.List; - +import java.util.Timer; +import java.util.TimerTask; /** * {@hide} */ @@ -83,8 +84,21 @@ public class CDMAPhone extends PhoneBase { // mEriFileLoadedRegistrants are informed after the ERI text has been loaded private RegistrantList mEriFileLoadedRegistrants = new RegistrantList(); + + // mECMExitRespRegistrant is informed after the phone has been exited + //the emergency callback mode + //keep track of if phone is in emergency callback mode + private boolean mIsPhoneInECMState; + private Registrant mECMExitRespRegistrant; private String mEsn; private String mMeid; + + // A runnable which is used to automatically exit from ECM after a period of time. + private Runnable mExitEcmRunnable = new Runnable() { + public void run() { + exitEmergencyCallbackMode(); + } + }; Registrant mPostDialHandler; @@ -122,13 +136,16 @@ public class CDMAPhone extends PhoneBase { mCM.setOnCallRing(h, EVENT_CALL_RING, null); mSST.registerForNetworkAttach(h, EVENT_REGISTERED_TO_NETWORK, null); mCM.registerForNVReady(h, EVENT_NV_READY, null); - mCM.registerForCdmaCallWaiting(h,EVENT_CDMA_CALL_WAITING,null); - mCM.setEmergencyCallbackMode(h, EVENT_EMERGENCY_CALLBACK_MODE, null); + mCM.setEmergencyCallbackMode(h, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null); //Change the system setting SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE, new Integer(RILConstants.CDMA_PHONE).toString()); + + // TODO(Moto): Is this needed to handle phone crashes and/or power cycling? + String inEcm=SystemProperties.get(PROPERTY_INECM_MODE, "false"); + mIsPhoneInECMState = inEcm.equals("true"); } public void dispose() { @@ -143,7 +160,7 @@ public class CDMAPhone extends PhoneBase { mSST.unregisterForNetworkAttach(h); //EVENT_REGISTERED_TO_NETWORK mCM.unSetOnSuppServiceNotification(h); mCM.unSetOnCallRing(h); - mCM.unregisterForCdmaCallWaiting(h); + //Force all referenced classes to unregister their former registered events mCT.dispose(); @@ -370,8 +387,8 @@ public class CDMAPhone extends PhoneBase { return mRuimRecords.getMdnNumber(); } - public String getMin() { - return mRuimRecords.getMin(); + public String getCdmaMIN() { + return mRuimRecords.getCdmaMin(); } public void getCallWaiting(Message onComplete) { @@ -434,7 +451,7 @@ public class CDMAPhone extends PhoneBase { } public void setOnPostDialCharacter(Handler h, int what, Object obj) { - Log.e(LOG_TAG, "setOnPostDialCharacter: not possible in CDMA"); + mPostDialHandler = new Registrant(h, what, obj); } public boolean handlePinMmi(String dialString) { @@ -478,6 +495,30 @@ public class CDMAPhone extends PhoneBase { mDataConnection.setDataOnRoamingEnabled(enable); } + public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) { + mCM.registerForCdmaOtaProvision(h, what, obj); + } + + public void unregisterForCdmaOtaStatusChange(Handler h) { + mCM.unregisterForCdmaOtaProvision(h); + } + + public void setOnEcbModeExitResponse(Handler h, int what, Object obj) { + mECMExitRespRegistrant = new Registrant (h, what, obj); + } + + public void unsetOnEcbModeExitResponse(Handler h) { + mECMExitRespRegistrant.clear(); + } + + public void registerForCallWaiting(Handler h, int what, Object obj) { + Log.e(LOG_TAG, "method registerForCallWaiting is NOT yet supported in CDMA"); + } + + public void unregisterForCallWaiting(Handler h) { + Log.e(LOG_TAG, "method unregisterForCallWaiting is NOT yet supported in CDMA"); + } + public String getIpAddress(String apnType) { return mDataConnection.getIpAddress(); } @@ -565,7 +606,7 @@ public class CDMAPhone extends PhoneBase { mCM.stopDtmf(null); } - public void sendBurstDtmf(String dtmfString) { + public void sendBurstDtmf(String dtmfString, Message onComplete) { boolean check = true; for (int itr = 0;itr < dtmfString.length(); itr++) { if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) { @@ -576,7 +617,7 @@ public class CDMAPhone extends PhoneBase { } } if ((mCT.state == Phone.State.OFFHOOK)&&(check)) { - mCM.sendBurstDtmf(dtmfString, null); + mCM.sendBurstDtmf(dtmfString, onComplete); } } @@ -593,7 +634,7 @@ public class CDMAPhone extends PhoneBase { } public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) { - Log.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA"); + Log.e(LOG_TAG, "setOutgoingCallerIdDisplay: not possible in CDMA"); } public void enableLocationUpdates() { @@ -630,7 +671,14 @@ public class CDMAPhone extends PhoneBase { //TODO: Where can we get this value has to be clarified with QC //return mSIMRecords.getVoiceMailNumber(); // throw new RuntimeException(); - return "12345"; + return "*86"; + } + + /* Returns Number of Voicemails + * @hide + */ + public int getCountVoiceMessages() { + return mRuimRecords.getCountVoiceMessages(); } public String getVoiceMailAlphaTag() { @@ -648,7 +696,15 @@ public class CDMAPhone extends PhoneBase { } public boolean enableDataConnectivity() { - return mDataConnection.setDataEnabled(true); + + // block data activities when phone is in emergency callback mode + if (mIsPhoneInECMState) { + Intent intent = new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS); + ActivityManagerNative.broadcastStickyIntent(intent, null); + return false; + } else { + return mDataConnection.setDataEnabled(true); + } } public void disableLocationUpdates() { @@ -691,7 +747,7 @@ public class CDMAPhone extends PhoneBase { return null; } - /** + /** * Notify any interested party of a Phone state change. */ /*package*/ void notifyPhoneStateChanged() { @@ -736,6 +792,13 @@ public class CDMAPhone extends PhoneBase { mUnknownConnectionRegistrants.notifyResult(this); } + void sendEmergencyCallbackModeChange(){ + //Send an Intent + Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); + intent.putExtra(PHONE_IN_ECM_STATE, mIsPhoneInECMState); + ActivityManagerNative.broadcastStickyIntent(intent,null); + } + /*package*/ void updateMessageWaitingIndicator(boolean mwi) { // this also calls notifyMessageWaitingIndicator() @@ -761,6 +824,51 @@ public class CDMAPhone extends PhoneBase { mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, fc, null)); } + + @Override + public void exitEmergencyCallbackMode() { + // Send a message which will invoke handleExitEmergencyCallbackMode + mCM.exitEmergencyCallbackMode(h.obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE)); + } + + private void handleEnterEmergencyCallbackMode(Message msg) { + Log.d(LOG_TAG, "Event EVENT_EMERGENCY_CALLBACK_MODE Received"); + // if phone is not in ECM mode, and it's changed to ECM mode + if (mIsPhoneInECMState == false) { + mIsPhoneInECMState = true; + // notify change + sendEmergencyCallbackModeChange(); + setSystemProperty(PROPERTY_INECM_MODE, "true"); + + // Post this runnable so we will automatically exit + // if no one invokes exitEmergencyCallbackMode() directly. + // TODO(Moto): Get the delay a property so it can be adjusted + long delayInMillis = 300000; // 30,000 millis == 5 minutes + h.postDelayed(mExitEcmRunnable, delayInMillis); + } + } + + private void handleExitEmergencyCallbackMode(Message msg) { + Log.d(LOG_TAG, "Event EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE Received"); + AsyncResult ar = (AsyncResult)msg.obj; + + // Remove pending exit ECM runnable, if any + h.removeCallbacks(mExitEcmRunnable); + + if (mECMExitRespRegistrant != null) { + mECMExitRespRegistrant.notifyRegistrant(ar); + } + // if exiting ecm success + if (ar.exception == null) { + if (mIsPhoneInECMState) { + mIsPhoneInECMState = false; + setSystemProperty(PROPERTY_INECM_MODE, "false"); + } + // send an Intent + sendEmergencyCallbackModeChange(); + } + } + //***** Inner Classes class MyHandler extends Handler { MyHandler() { @@ -770,6 +878,7 @@ public class CDMAPhone extends PhoneBase { super(l); } + @Override public void handleMessage(Message msg) { AsyncResult ar; Message onComplete; @@ -806,12 +915,16 @@ public class CDMAPhone extends PhoneBase { } break; - case EVENT_EMERGENCY_CALLBACK_MODE: { - Log.d(LOG_TAG, "Event EVENT_EMERGENCY_CALLBACK_MODE Received"); - Intent intent = - new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_ENTERED); - ActivityManagerNative.broadcastStickyIntent(intent, null); + case EVENT_EMERGENCY_CALLBACK_MODE_ENTER:{ + handleEnterEmergencyCallbackMode(msg); } + break; + + case EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE:{ + handleExitEmergencyCallbackMode(msg); + } + break; + case EVENT_RUIM_RECORDS_LOADED:{ Log.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received"); } @@ -852,11 +965,7 @@ public class CDMAPhone extends PhoneBase { Log.d(LOG_TAG, "ERI read, notify registrants"); mEriFileLoadedRegistrants.notifyRegistrants(); } - } - break; - - case EVENT_CDMA_CALL_WAITING:{ - Log.d(LOG_TAG, "Event EVENT_CDMA_CALL_WAITING Received"); + setSystemProperty(PROPERTY_INECM_MODE,"false"); } break; @@ -867,26 +976,26 @@ public class CDMAPhone extends PhoneBase { } } - /** - * Retrieves the PhoneSubInfo of the CDMAPhone - */ - public PhoneSubInfo getPhoneSubInfo(){ + /** + * Retrieves the PhoneSubInfo of the CDMAPhone + */ + public PhoneSubInfo getPhoneSubInfo() { return mSubInfo; - } + } - /** - * Retrieves the IccSmsInterfaceManager of the CDMAPhone - */ - public IccSmsInterfaceManager getIccSmsInterfaceManager(){ - return mRuimSmsInterfaceManager; - } + /** + * Retrieves the IccSmsInterfaceManager of the CDMAPhone + */ + public IccSmsInterfaceManager getIccSmsInterfaceManager() { + return mRuimSmsInterfaceManager; + } - /** - * Retrieves the IccPhoneBookInterfaceManager of the CDMAPhone - */ - public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){ - return mRuimPhoneBookInterfaceManager; - } + /** + * Retrieves the IccPhoneBookInterfaceManager of the CDMAPhone + */ + public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager() { + return mRuimPhoneBookInterfaceManager; + } public void registerForNvLoaded(Handler h, int what, Object obj) { Registrant r = new Registrant (h, what, obj); @@ -906,97 +1015,146 @@ public class CDMAPhone extends PhoneBase { mEriFileLoadedRegistrants.remove(h); } - // override for allowing access from other classes of this package - /** - * {@inheritDoc} - */ - public final void setSystemProperty(String property, String value) { - super.setSystemProperty(property, value); - } - - /** - * {@inheritDoc} - */ - public Handler getHandler(){ - return h; - } - - /** - * {@inheritDoc} - */ - public IccFileHandler getIccFileHandler(){ - return this.mIccFileHandler; - } - - /** - * Set the TTY mode of the CDMAPhone - */ - public void setTTYMode(int ttyMode, Message onComplete) { - this.mCM.setTTYMode(ttyMode, onComplete); -} - - /** - * Queries the TTY mode of the CDMAPhone - */ - public void queryTTYMode(Message onComplete) { - this.mCM.queryTTYMode(onComplete); - } - - /** - * Sends Exit EmergencyCallbackMode Exit request on CDMAPhone - */ - public void exitEmergencyCallbackMode(Message onComplete) { - this.mCM.exitEmergencyCallbackMode(onComplete); - } - - /** - * Activate or deactivate cell broadcast SMS. - * - * @param activate - * 0 = activate, 1 = deactivate - * @param response - * Callback message is empty on completion - */ - public void activateCellBroadcastSms(int activate, Message response) { - mSMS.activateCellBroadcastSms(activate, response); - } - - /** - * Query the current configuration of cdma cell broadcast SMS. - * - * @param response - * Callback message is empty on completion - */ - public void getCellBroadcastSmsConfig(Message response){ - mSMS.getCellBroadcastSmsConfig(response); - } - - /** - * Configure cdma cell broadcast SMS. - * - * @param response - * Callback message is empty on completion - */ - public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){ - mSMS.setCellBroadcastConfig(configValuesArray, response); - } - - public void registerForOtaSessionStatus(Handler h, int what, Object obj){ - mCM.registerForOtaSessionStatus(h, what, obj); - } - - public void unregisterForOtaSessionStatus(Handler h){ - mCM.unregisterForOtaSessionStatus(h); - } - -/** - * TODO(Teleca): The code in getCdmaEriIconIndex, getCdmaEriIconMode & getCdmaEriText share a - * lot of logic, refactor. - */ + // override for allowing access from other classes of this package /** - * Returns the CDMA ERI icon index to display, - * it returns 1, EriInfo.ROAMING_INDICATOR_OFF, in case there is no icon to display + * {@inheritDoc} */ + public final void setSystemProperty(String property, String value) { + super.setSystemProperty(property, value); + } + + /** + * {@inheritDoc} + */ + public Handler getHandler() { + return h; + } + + /** + * {@inheritDoc} + */ + public IccFileHandler getIccFileHandler() { + return this.mIccFileHandler; + } + + /** + * Set the TTY mode of the CDMAPhone + */ + public void setTTYMode(int ttyMode, Message onComplete) { + this.mCM.setTTYMode(ttyMode, onComplete); + } + + /** + * Queries the TTY mode of the CDMAPhone + */ + public void queryTTYMode(Message onComplete) { + this.mCM.queryTTYMode(onComplete); + } + + /** + * Activate or deactivate cell broadcast SMS. + * + * @param activate 0 = activate, 1 = deactivate + * @param response Callback message is empty on completion + */ + public void activateCellBroadcastSms(int activate, Message response) { + mSMS.activateCellBroadcastSms(activate, response); + } + + /** + * Query the current configuration of cdma cell broadcast SMS. + * + * @param response Callback message is empty on completion + */ + public void getCellBroadcastSmsConfig(Message response) { + mSMS.getCellBroadcastSmsConfig(response); + } + + /** + * Configure cdma cell broadcast SMS. + * + * @param response Callback message is empty on completion + */ + public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) { + mSMS.setCellBroadcastConfig(configValuesArray, response); + } + + public static final String IS683A_FEATURE_CODE = "*228" ; + public static final int IS683A_FEATURE_CODE_NUM_DIGITS = 4 ; + public static final int IS683A_SYS_SEL_CODE_NUM_DIGITS = 2 ; + public static final int IS683A_SYS_SEL_CODE_OFFSET = 4; + + private static final int IS683_CONST_800MHZ_A_BAND = 0; + private static final int IS683_CONST_800MHZ_B_BAND = 1; + private static final int IS683_CONST_1900MHZ_A_BLOCK = 2; + private static final int IS683_CONST_1900MHZ_B_BLOCK = 3; + private static final int IS683_CONST_1900MHZ_C_BLOCK = 4; + private static final int IS683_CONST_1900MHZ_D_BLOCK = 5; + private static final int IS683_CONST_1900MHZ_E_BLOCK = 6; + private static final int IS683_CONST_1900MHZ_F_BLOCK = 7; + + private boolean isIs683OtaSpDialStr(String dialStr) { + int sysSelCodeInt; + boolean isOtaspDialString = false; + int dialStrLen = dialStr.length(); + + if (dialStrLen == IS683A_FEATURE_CODE_NUM_DIGITS) { + if (dialStr.equals(IS683A_FEATURE_CODE)) { + isOtaspDialString = true; + } + } else if ((dialStr.regionMatches(0, IS683A_FEATURE_CODE, 0, + IS683A_FEATURE_CODE_NUM_DIGITS) == true) + && (dialStrLen >= + (IS683A_FEATURE_CODE_NUM_DIGITS + IS683A_SYS_SEL_CODE_NUM_DIGITS))) { + StringBuilder sb = new StringBuilder(dialStr); + // Separate the System Selection Code into its own string + char[] sysSel = new char[2]; + sb.delete(0, IS683A_SYS_SEL_CODE_OFFSET); + sb.getChars(0, IS683A_SYS_SEL_CODE_NUM_DIGITS, sysSel, 0); + + if ((PhoneNumberUtils.isISODigit(sysSel[0])) + && (PhoneNumberUtils.isISODigit(sysSel[1]))) { + String sysSelCode = new String(sysSel); + sysSelCodeInt = Integer.parseInt((String)sysSelCode); + switch (sysSelCodeInt) { + case IS683_CONST_800MHZ_A_BAND: + case IS683_CONST_800MHZ_B_BAND: + case IS683_CONST_1900MHZ_A_BLOCK: + case IS683_CONST_1900MHZ_B_BLOCK: + case IS683_CONST_1900MHZ_C_BLOCK: + case IS683_CONST_1900MHZ_D_BLOCK: + case IS683_CONST_1900MHZ_E_BLOCK: + case IS683_CONST_1900MHZ_F_BLOCK: + isOtaspDialString = true; + break; + + default: + break; + } + } + } + return isOtaspDialString; + } + + /** + * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier + * OTASP dial string. + * + * @param dialStr the number to look up. + * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string + */ + @Override + public boolean isOtaSpNumber(String dialStr){ + boolean isOtaSpNum = false; + if(dialStr != null){ + isOtaSpNum=isIs683OtaSpDialStr(dialStr); + if(isOtaSpNum == false){ + //TO DO:Add carrier specific OTASP number detection here. + } + } + return isOtaSpNum; + } + @Override public int getCdmaEriIconIndex() { int roamInd = getServiceState().getCdmaRoamingIndicator(); diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java index a1d362fb600f5..c02fcd4a3a8e2 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java @@ -24,6 +24,7 @@ import android.os.RegistrantList; import android.telephony.PhoneNumberUtils; import android.telephony.ServiceState; import android.util.Log; +import android.os.SystemProperties; import com.android.internal.telephony.CallStateException; import com.android.internal.telephony.CallTracker; @@ -31,11 +32,12 @@ import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.Connection; import com.android.internal.telephony.DriverCall; import com.android.internal.telephony.Phone; -import com.android.internal.telephony.PhoneProxy; +import com.android.internal.telephony.TelephonyProperties; import java.util.ArrayList; import java.util.List; + /** * {@hide} */ @@ -69,11 +71,12 @@ public final class CdmaCallTracker extends CallTracker { CdmaConnection pendingMO; boolean hangupPendingMO; - + boolean pendingCallInECM=false; CDMAPhone phone; boolean desiredMute = false; // false = mute off + int pendingCallClirMode; Phone.State state = Phone.State.IDLE; @@ -115,6 +118,7 @@ public final class CdmaCallTracker extends CallTracker { } + @Override protected void finalize() { Log.d(LOG_TAG, "CdmaCallTracker finalized"); } @@ -204,7 +208,15 @@ public final class CdmaCallTracker extends CallTracker { // Always unmute when initiating a new call setMute(false); - cm.dial(pendingMO.address, clirMode, obtainCompleteMessage()); + String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false"); + if(inEcm.equals("false")) { + cm.dial(pendingMO.address, clirMode, obtainCompleteMessage()); + } else { + phone.exitEmergencyCallbackMode(); + phone.setOnEcbModeExitResponse(this,EVENT_EXIT_ECM_RESPONSE_CDMA, null); + pendingCallClirMode=clirMode; + pendingCallInECM=true; + } } updatePhoneState(); @@ -536,6 +548,9 @@ public final class CdmaCallTracker extends CallTracker { droppedDuringPoll.add(pendingMO); pendingMO = null; hangupPendingMO = false; + if( pendingCallInECM) { + pendingCallInECM = false; + } } if (newRinging != null) { @@ -847,8 +862,17 @@ public final class CdmaCallTracker extends CallTracker { handleRadioNotAvailable(); break; + case EVENT_EXIT_ECM_RESPONSE_CDMA: + //no matter the result, we still do the same here + if (pendingCallInECM) { + cm.dial(pendingMO.address, pendingCallClirMode, obtainCompleteMessage()); + pendingCallInECM = false; + } + phone.unsetOnEcbModeExitResponse(this); + break; + default:{ - throw new RuntimeException("unexpected event not handled"); + throw new RuntimeException("unexpected event not handled"); } } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallWaiting.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallWaiting.java deleted file mode 100644 index 64841d7ed0328..0000000000000 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallWaiting.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.telephony.cdma; - -import com.android.internal.telephony.CdmaInformationRecord; - -public class CdmaCallWaiting { - public String number; - public int numberPresentation; - public String name; - - public CdmaInformationRecord.CdmaSignalInfoRec signalInfoRecord = - new CdmaInformationRecord.CdmaSignalInfoRec(); - - @Override - public String toString() { - return "CdmaCallWaiting: {" + " number: " + number + " numberPresentation: " - + numberPresentation + " name: " + name + " signalInfoRecord: " - + signalInfoRecord + " }"; - } -} diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallWaitingNotification.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallWaitingNotification.java new file mode 100644 index 0000000000000..54dec48e84354 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallWaitingNotification.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony.cdma; + +/** + * Represents a Supplementary Service Notification received from the network. + * + * {@hide} + */ +public class CdmaCallWaitingNotification { + public String number =null; + public int numberPresentation = 0; + public String name = null; + public int namePresentation = 0; + public int isPresent = 0; + public int signalType = 0; + public int alertPitch = 0; + public int signal = 0; + + + public String toString() + { + return super.toString() + "Call Waiting Notification " + + " number: " + number + + " numberPresentation: " + numberPresentation + + " name: " + name + + " namePresentation: " + namePresentation + + " isPresent: " + isPresent + + " signalType: " + signalType + + " alertPitch: " + alertPitch + + " signal: " + signal ; + } + +} diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java index 0a237c6fb942c..32442f60a0b30 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java @@ -48,7 +48,7 @@ public class CdmaConnection extends Connection { String postDialString; // outgoing calls only boolean isIncoming; boolean disconnected; - + String cnapName; int index; // index in CdmaCallTracker.connections[], -1 if unassigned /* @@ -74,6 +74,8 @@ public class CdmaConnection extends Connection { DisconnectCause cause = DisconnectCause.NOT_DISCONNECTED; PostDialState postDialState = PostDialState.NOT_STARTED; int numberPresentation = Connection.PRESENTATION_ALLOWED; + int cnapNamePresentation = Connection.PRESENTATION_ALLOWED; + Handler h; @@ -86,10 +88,19 @@ public class CdmaConnection extends Connection { static final int EVENT_WAKE_LOCK_TIMEOUT = 4; //***** Constants - static final int PAUSE_DELAY_FIRST_MILLIS = 100; - static final int PAUSE_DELAY_MILLIS = 3 * 1000; static final int WAKE_LOCK_TIMEOUT_MILLIS = 60*1000; - + static final int PAUSE_DELAY_MILLIS = 2 * 1000; + + // TODO(Moto): These should be come from a resourse file + // at a minimum as different carriers may want to use + // different characters and our general default is "," & ";". + // Furthermore Android supports contacts that have phone + // numbers entered as strings so '1-800-164flowers' would not + // be handled as expected. Both issues need to be resolved. + static final char CUSTOMERIZED_WAIT_CHAR_UPPER ='W'; + static final char CUSTOMERIZED_WAIT_CHAR_LOWER ='w'; + static final char CUSTOMERIZED_PAUSE_CHAR_UPPER ='P'; + static final char CUSTOMERIZED_PAUSE_CHAR_LOWER ='p'; //***** Inner Classes class MyHandler extends Handler { @@ -126,6 +137,8 @@ public class CdmaConnection extends Connection { isIncoming = dc.isMT; createTime = System.currentTimeMillis(); + cnapName = dc.name; + cnapNamePresentation = dc.namePresentation; numberPresentation = dc.numberPresentation; this.index = index; @@ -134,6 +147,16 @@ public class CdmaConnection extends Connection { parent.attach(this, dc); } + CdmaConnection () { + owner = null; + h = null; + address = null; + index = -1; + parent = null; + isIncoming = true; + createTime = System.currentTimeMillis(); + } + /** This is an MO call, created when dialing */ /*package*/ CdmaConnection (Context context, String dialString, CdmaCallTracker ct, CdmaCall parent) { @@ -144,6 +167,9 @@ public class CdmaConnection extends Connection { h = new MyHandler(owner.getLooper()); this.dialString = dialString; + Log.d(LOG_TAG, "[CDMAConn] CdmaConnection: dialString=" + dialString); + dialString = formatDialString(dialString); + Log.d(LOG_TAG, "[CDMAConn] CdmaConnection:formated dialString=" + dialString); this.address = PhoneNumberUtils.extractNetworkPortion(dialString); this.postDialString = PhoneNumberUtils.extractPostDialPortion(dialString); @@ -151,10 +177,15 @@ public class CdmaConnection extends Connection { index = -1; isIncoming = false; + cnapName = null; + cnapNamePresentation = 0; + numberPresentation = 0; createTime = System.currentTimeMillis(); - this.parent = parent; - parent.attachFake(this, CdmaCall.State.DIALING); + if (parent != null) { + this.parent = parent; + parent.attachFake(this, CdmaCall.State.DIALING); + } } public void dispose() { @@ -186,10 +217,22 @@ public class CdmaConnection extends Connection { return (isIncoming ? "incoming" : "outgoing"); } + public String getOrigDialString(){ + return dialString; + } + public String getAddress() { return address; } + public String getCnapName() { + return cnapName; + } + + public int getCnapNamePresentation() { + return cnapNamePresentation; + } + public CdmaCall getCall() { return parent; } @@ -320,6 +363,16 @@ public class CdmaConnection extends Connection { } } + /** + * Used for 3way call only + */ + void update (CdmaConnection c) { + address = c.address; + cnapName = c.cnapName; + cnapNamePresentation = c.cnapNamePresentation; + numberPresentation = c.numberPresentation; + } + public void cancelPostDial() { setPostDialState(PostDialState.CANCELLED); } @@ -355,7 +408,7 @@ public class CdmaConnection extends Connection { case CallFailCause.CDMA_LOCKED_UNTIL_POWER_CYCLE: return DisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE; case CallFailCause.CDMA_DROP: - return DisconnectCause.CDMA_DROP; + return DisconnectCause.LOST_SIGNAL; // TODO(Moto): wink/dave changed from CDMA_DROP; case CallFailCause.CDMA_INTERCEPT: return DisconnectCause.CDMA_INTERCEPT; case CallFailCause.CDMA_REORDER: @@ -434,6 +487,20 @@ public class CdmaConnection extends Connection { changed = true; } + // A null cnapName should be the same as "" + if (null != dc.name) { + if (cnapName != dc.name) { + cnapName = dc.name; + changed = true; + } + } else { + cnapName = ""; + // TODO(Moto): Should changed = true if cnapName wasn't previously "" + } + log("--dssds----"+cnapName); + cnapNamePresentation = dc.namePresentation; + numberPresentation = dc.numberPresentation; + if (newParent != parent) { if (parent != null) { parent.detach(this); @@ -533,25 +600,13 @@ public class CdmaConnection extends Connection { if (PhoneNumberUtils.is12Key(c)) { owner.cm.sendDtmf(c, h.obtainMessage(EVENT_DTMF_DONE)); } else if (c == PhoneNumberUtils.PAUSE) { - // From TS 22.101: + setPostDialState(PostDialState.PAUSE); - // "The first occurrence of the "DTMF Control Digits Separator" - // shall be used by the ME to distinguish between the addressing - // digits (i.e. the phone number) and the DTMF digits...." - - if (nextPostDialChar == 1) { - // The first occurrence. - // We don't need to pause here, but wait for just a bit anyway - h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE), - PAUSE_DELAY_FIRST_MILLIS); - } else { - // It continues... - // "Upon subsequent occurrences of the separator, the UE shall - // pause again for 3 seconds (\u00B1 20 %) before sending any - // further DTMF digits." - h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE), + // Upon occurrences of the separator, the UE shall + // pause again for 2 seconds before sending any + // further DTMF digits. + h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE), PAUSE_DELAY_MILLIS); - } } else if (c == PhoneNumberUtils.WAIT) { setPostDialState(PostDialState.WAIT); } else if (c == PhoneNumberUtils.WILD) { @@ -563,17 +618,40 @@ public class CdmaConnection extends Connection { return true; } - public String - getRemainingPostDialString() { + public String getRemainingPostDialString() { if (postDialState == PostDialState.CANCELLED - || postDialState == PostDialState.COMPLETE - || postDialString == null - || postDialString.length() <= nextPostDialChar - ) { + || postDialState == PostDialState.COMPLETE + || postDialString == null + || postDialString.length() <= nextPostDialChar) { return ""; } - return postDialString.substring(nextPostDialChar); + String subStr = postDialString.substring(nextPostDialChar); + if (subStr != null) { + int wIndex = subStr.indexOf(PhoneNumberUtils.WAIT); + int pIndex = subStr.indexOf(PhoneNumberUtils.PAUSE); + + // TODO(Moto): Courtesy of jsh; is this simpler expression equivalent? + // + // if (wIndex > 0 && (wIndex < pIndex || pIndex <= 0)) { + // subStr = subStr.substring(0, wIndex); + // } else if (pIndex > 0) { + // subStr = subStr.substring(0, pIndex); + // } + + if (wIndex > 0 && pIndex > 0) { + if (wIndex > pIndex) { + subStr = subStr.substring(0, pIndex); + } else { + subStr = subStr.substring(0, wIndex); + } + } else if (wIndex > 0) { + subStr = subStr.substring(0, wIndex); + } else if (pIndex > 0) { + subStr = subStr.substring(0, pIndex); + } + } + return subStr; } @Override @@ -591,8 +669,7 @@ public class CdmaConnection extends Connection { releaseWakeLock(); } - private void - processNextPostDialChar() { + void processNextPostDialChar() { char c = 0; Registrant postDialHandler; @@ -698,21 +775,18 @@ public class CdmaConnection extends Connection { postDialState = s; } - private void - createWakeLock(Context context) { - PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + private void createWakeLock(Context context) { + PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG); } - private void - acquireWakeLock() { + private void acquireWakeLock() { log("acquireWakeLock"); mPartialWakeLock.acquire(); } - private void - releaseWakeLock() { - synchronized(mPartialWakeLock) { + private void releaseWakeLock() { + synchronized (mPartialWakeLock) { if (mPartialWakeLock.isHeld()) { log("releaseWakeLock"); mPartialWakeLock.release(); @@ -720,6 +794,119 @@ public class CdmaConnection extends Connection { } } + private static boolean isPause(char c) { + if (c == CUSTOMERIZED_PAUSE_CHAR_UPPER || c == CUSTOMERIZED_PAUSE_CHAR_LOWER + || c == PhoneNumberUtils.PAUSE) { + return true; + } else { + return false; + } + } + + private static boolean isWait(char c) { + if (c == CUSTOMERIZED_WAIT_CHAR_LOWER || c == CUSTOMERIZED_WAIT_CHAR_UPPER + || c == PhoneNumberUtils.WAIT) { + return true; + } else { + return false; + } + } + + /** + * format string + * convert "+" to "011" + * handle corner cases for PAUSE/WAIT + * If PAUSE/WAIT sequence at the end,ignore them + * If PAUSE/WAIT sequence in the middle, then if there is any WAIT + * in PAUSE/WAIT sequence, treat them like WAIT + * If PAUSE followed by WAIT or WAIT followed by PAUSE in the middle, + * treat them like just PAUSE or WAIT + */ + private static String formatDialString(String phoneNumber) { + if (phoneNumber == null) { + return null; + } + int length = phoneNumber.length(); + StringBuilder ret = new StringBuilder(); + + // TODO(Moto): Modifying the for loop index is confusing, a + // while loop is probably better and overall this code is + // hard to follow. If this was routine was refactored and + // used several private methods with good names to make it + // easier to follow. + for (int i = 0; i < length; i++) { + char c = phoneNumber.charAt(i); + + if (PhoneNumberUtils.isDialable(c)) { + if (c == '+') { + // TODO(Moto): Is this valid for "all" countries???? + // should probably be pulled from a resource based + // on current contry code (MCC). + ret.append("011"); + } else { + ret.append(c); + } + } else if (isPause(c) || isWait(c)) { + if (i < length - 1) { // if PAUSE/WAIT not at the end + int index = 0; + boolean wMatched = false; + for (index = i + 1; index < length; index++) { + char cNext = phoneNumber.charAt(index); + // if there is any W inside P/W sequence,mark it + if (isWait(cNext)) { + wMatched = true; + } + // if any characters other than P/W chars after P/W sequence + // we break out the loop and append the correct + if (!isWait(cNext) && !isPause(cNext)) { + break; + } + } + if (index == length) { + // it means there is no dialable character after PAUSE/WAIT + i = length - 1; + break; + } else {// means index "; + } + } +} diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java index a3d00d73db026..f12e7e399e3aa 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java @@ -17,15 +17,18 @@ package com.android.internal.telephony.cdma; +import android.app.Activity; import android.app.PendingIntent; import android.content.ContentValues; import android.database.Cursor; import android.database.SQLException; import android.os.AsyncResult; import android.os.Message; +import android.provider.Telephony.Sms.Intents; import android.util.Config; import android.util.Log; +import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.SmsHeader; import com.android.internal.telephony.SmsMessageBase; import com.android.internal.telephony.SMSDispatcher; @@ -330,10 +333,10 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ - protected void acknowledgeLastIncomingSms(boolean success, Message response){ + protected void acknowledgeLastIncomingSms(boolean success, int result, Message response){ // FIXME unit test leaves cm == null. this should change if (mCm != null) { - mCm.acknowledgeLastIncomingCdmaSms(success, response); + mCm.acknowledgeLastIncomingCdmaSms(success, resultToCause(result), response); } } @@ -352,4 +355,17 @@ final class CdmaSMSDispatcher extends SMSDispatcher { mCm.setCdmaBroadcastConfig(configValuesArray, response); } + private int resultToCause(int rc) { + switch (rc) { + case Activity.RESULT_OK: + case Intents.RESULT_SMS_HANDLED: + // Cause code is ignored on success. + return 0; + case Intents.RESULT_SMS_OUT_OF_MEMORY: + return CommandsInterface.CDMA_SMS_FAIL_CAUSE_RESOURCE_SHORTAGE; + case Intents.RESULT_SMS_GENERIC_ERROR: + default: + return CommandsInterface.CDMA_SMS_FAIL_CAUSE_OTHER_TERMINAL_PROBLEM; + } + } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index dbb0f93037395..8ecdecd4d9c77 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -24,6 +24,7 @@ import android.database.ContentObserver; import android.os.AsyncResult; import android.os.Handler; import android.os.Message; +import android.os.PowerManager; import android.os.Registrant; import android.os.RegistrantList; import android.os.SystemClock; @@ -38,7 +39,9 @@ import android.telephony.cdma.CdmaCellLocation; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; +import android.util.Config; import android.util.TimeUtils; +import java.util.Calendar; import com.android.internal.telephony.CommandException; import com.android.internal.telephony.CommandsInterface; @@ -100,12 +103,26 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { private RegistrantList cdmaDataConnectionAttachedRegistrants = new RegistrantList(); private RegistrantList cdmaDataConnectionDetachedRegistrants = new RegistrantList(); + // Sometimes we get the NITZ time before we know what country we are in. + // Keep the time zone information from the NITZ string so we can fix + // the time zone once know the country. + private boolean mNeedFixZone = false; + private int mZoneOffset; + private boolean mZoneDst; + private long mZoneTime; private boolean mGotCountryCode = false; + String mSavedTimeZone; + long mSavedTime; + long mSavedAtTime; // We can't register for SIM_RECORDS_LOADED immediately because the // SIMRecords object may not be instantiated yet. private boolean mNeedToRegForRuimLoaded; + // Wake lock used while setting time of day. + private PowerManager.WakeLock mWakeLock; + private static final String WAKELOCK_TAG = "ServiceStateTracker"; + // Keep track of SPN display rules, so we only broadcast intent if something changes. private String curSpn = null; private String curEriText = null; @@ -134,7 +151,8 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { @Override public void onChange(boolean selfChange) { Log.i("CdmaServiceStateTracker", "Auto time state called ..."); - //NOTE in CDMA NITZ is not used + revertToNitz(); + } }; @@ -152,10 +170,15 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { newCellLoc = new CdmaCellLocation(); mSignalStrength = new SignalStrength(); + PowerManager powerManager = + (PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE); + mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG); + cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); cm.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null); cm.registerForNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED_CDMA, null); + cm.setOnNITZTime(this, EVENT_NITZ_TIME, null); cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null); cm.registerForRUIMReady(this, EVENT_RUIM_READY, null); @@ -188,6 +211,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { phone.unregisterForEriFileLoaded(this); phone.mRuimRecords.unregisterForRecordsLoaded(this); cm.unSetOnSignalStrengthUpdate(this); + cm.unSetOnNITZTime(this); cr.unregisterContentObserver(this.mAutoTimeObserver); } @@ -378,6 +402,15 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { cm.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH)); break; + case EVENT_NITZ_TIME: + ar = (AsyncResult) msg.obj; + + String nitzString = (String)((Object[])ar.result)[0]; + long nitzReceiveTime = ((Long)((Object[])ar.result)[1]).longValue(); + + setTimeFromNITZString(nitzString, nitzReceiveTime); + break; + case EVENT_SIGNAL_STRENGTH_UPDATE: // This is a notification from // CommandsInterface.setOnSignalStrengthUpdate @@ -800,8 +833,44 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { return ret; } - private void - pollStateDone() { + private void fixTimeZone(String isoCountryCode) { + TimeZone zone = null; + // If the offset is (0, false) and the time zone property + // is set, use the time zone property rather than GMT. + String zoneName = SystemProperties.get(TIMEZONE_PROPERTY); + if ((mZoneOffset == 0) && (mZoneDst == false) && (zoneName != null) + && (zoneName.length() > 0) + && (Arrays.binarySearch(GMT_COUNTRY_CODES, isoCountryCode) < 0)) { + // For NITZ string without time zone, + // need adjust time to reflect default time zone setting + zone = TimeZone.getDefault(); + long tzOffset; + tzOffset = zone.getOffset(System.currentTimeMillis()); + if (getAutoTime()) { + setAndBroadcastNetworkSetTime(System.currentTimeMillis() - tzOffset); + } else { + // Adjust the saved NITZ time to account for tzOffset. + mSavedTime = mSavedTime - tzOffset; + } + } else if (isoCountryCode.equals("")) { + // Country code not found. This is likely a test network. + // Get a TimeZone based only on the NITZ parameters (best guess). + zone = getNitzTimeZone(mZoneOffset, mZoneDst, mZoneTime); + } else { + zone = TimeUtils.getTimeZone(mZoneOffset, mZoneDst, mZoneTime, isoCountryCode); + } + + mNeedFixZone = false; + + if (zone != null) { + if (getAutoTime()) { + setAndBroadcastNetworkSetTimeZone(zone.getID()); + } + saveNitzTimeZone(zone.getID()); + } + } + + private void pollStateDone() { if (DBG) log("Poll ServiceState done: oldSS=[" + ss + "] newSS=[" + newSS + "]"); boolean hasRegistered = @@ -896,9 +965,9 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { if (operatorNumeric == null) { phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, ""); } else { - String iso = ""; + String isoCountryCode = ""; try{ - iso = MccTable.countryCodeForMcc(Integer.parseInt( + isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt( operatorNumeric.substring(0,3))); } catch ( NumberFormatException ex){ Log.w(LOG_TAG, "countryCodeForMcc error" + ex); @@ -906,8 +975,11 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { Log.w(LOG_TAG, "countryCodeForMcc error" + ex); } - phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, iso); + phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, isoCountryCode); mGotCountryCode = true; + if (mNeedFixZone) { + fixTimeZone(isoCountryCode); + } } phone.setSystemProperty(PROPERTY_OPERATOR_ISROAMING, @@ -1123,6 +1195,169 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { return cdmaRoaming && !(equalsOnsl || equalsOnss); } + + /** + * nitzReceiveTime is time_t that the NITZ time was posted + */ + + private + void setTimeFromNITZString (String nitz, long nitzReceiveTime) + { + // "yy/mm/dd,hh:mm:ss(+/-)tz" + // tz is in number of quarter-hours + + long start = SystemClock.elapsedRealtime(); + Log.i(LOG_TAG, "NITZ: " + nitz + "," + nitzReceiveTime + + " start=" + start + " delay=" + (start - nitzReceiveTime)); + + try { + /* NITZ time (hour:min:sec) will be in UTC but it supplies the timezone + * offset as well (which we won't worry about until later) */ + Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + + c.clear(); + c.set(Calendar.DST_OFFSET, 0); + + String[] nitzSubs = nitz.split("[/:,+-]"); + + int year = 2000 + Integer.parseInt(nitzSubs[0]); + c.set(Calendar.YEAR, year); + + // month is 0 based! + int month = Integer.parseInt(nitzSubs[1]) - 1; + c.set(Calendar.MONTH, month); + + int date = Integer.parseInt(nitzSubs[2]); + c.set(Calendar.DATE, date); + + int hour = Integer.parseInt(nitzSubs[3]); + c.set(Calendar.HOUR, hour); + + int minute = Integer.parseInt(nitzSubs[4]); + c.set(Calendar.MINUTE, minute); + + int second = Integer.parseInt(nitzSubs[5]); + c.set(Calendar.SECOND, second); + + boolean sign = (nitz.indexOf('-') == -1); + + int tzOffset = Integer.parseInt(nitzSubs[6]); + + int dst = (nitzSubs.length >= 8 ) ? Integer.parseInt(nitzSubs[7]) + : 0; + + // The zone offset received from NITZ is for current local time, + // so DST correction is already applied. Don't add it again. + // + // tzOffset += dst * 4; + // + // We could unapply it if we wanted the raw offset. + + tzOffset = (sign ? 1 : -1) * tzOffset * 15 * 60 * 1000; + + TimeZone zone = null; + + // As a special extension, the Android emulator appends the name of + // the host computer's timezone to the nitz string. this is zoneinfo + // timezone name of the form Area!Location or Area!Location!SubLocation + // so we need to convert the ! into / + if (nitzSubs.length >= 9) { + String tzname = nitzSubs[8].replace('!','/'); + zone = TimeZone.getTimeZone( tzname ); + } + + String iso = SystemProperties.get(PROPERTY_OPERATOR_ISO_COUNTRY); + + if (zone == null) { + + if (mGotCountryCode) { + if (iso != null && iso.length() > 0) { + zone = TimeUtils.getTimeZone(tzOffset, dst != 0, + c.getTimeInMillis(), + iso); + } else { + // We don't have a valid iso country code. This is + // most likely because we're on a test network that's + // using a bogus MCC (eg, "001"), so get a TimeZone + // based only on the NITZ parameters. + zone = getNitzTimeZone(tzOffset, (dst != 0), c.getTimeInMillis()); + } + } + } + + if (zone == null) { + // We got the time before the country, so we don't know + // how to identify the DST rules yet. Save the information + // and hope to fix it up later. + + mNeedFixZone = true; + mZoneOffset = tzOffset; + mZoneDst = dst != 0; + mZoneTime = c.getTimeInMillis(); + } + + if (zone != null) { + if (getAutoTime()) { + setAndBroadcastNetworkSetTimeZone(zone.getID()); + } + saveNitzTimeZone(zone.getID()); + } + + String ignore = SystemProperties.get("gsm.ignore-nitz"); + if (ignore != null && ignore.equals("yes")) { + Log.i(LOG_TAG, "NITZ: Not setting clock because gsm.ignore-nitz is set"); + return; + } + + try { + mWakeLock.acquire(); + + if (getAutoTime()) { + long millisSinceNitzReceived + = SystemClock.elapsedRealtime() - nitzReceiveTime; + + if (millisSinceNitzReceived < 0) { + // Sanity check: something is wrong + Log.i(LOG_TAG, "NITZ: not setting time, clock has rolled " + + "backwards since NITZ time was received, " + + nitz); + return; + } + + if (millisSinceNitzReceived > Integer.MAX_VALUE) { + // If the time is this far off, something is wrong > 24 days! + Log.i(LOG_TAG, "NITZ: not setting time, processing has taken " + + (millisSinceNitzReceived / (1000 * 60 * 60 * 24)) + + " days"); + return; + } + + // Note: with range checks above, cast to int is safe + c.add(Calendar.MILLISECOND, (int)millisSinceNitzReceived); + + Log.i(LOG_TAG, "NITZ: Setting time of day to " + c.getTime() + + " NITZ receive delay(ms): " + millisSinceNitzReceived + + " gained(ms): " + + (c.getTimeInMillis() - System.currentTimeMillis()) + + " from " + nitz); + + setAndBroadcastNetworkSetTime(c.getTimeInMillis()); + Log.i(LOG_TAG, "NITZ: after Setting time of day"); + } + SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis())); + saveNitzTime(c.getTimeInMillis()); + if (Config.LOGV) { + long end = SystemClock.elapsedRealtime(); + Log.v(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start)); + } + } finally { + mWakeLock.release(); + } + } catch (RuntimeException ex) { + Log.e(LOG_TAG, "NITZ: Parsing NITZ time " + nitz, ex); + } + } + private boolean getAutoTime() { try { return Settings.System.getInt(phone.getContext().getContentResolver(), @@ -1132,6 +1367,58 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { } } + private void saveNitzTimeZone(String zoneId) { + mSavedTimeZone = zoneId; + } + + private void saveNitzTime(long time) { + mSavedTime = time; + mSavedAtTime = SystemClock.elapsedRealtime(); + } + + /** + * Set the timezone and send out a sticky broadcast so the system can + * determine if the timezone was set by the carrier. + * + * @param zoneId timezone set by carrier + */ + private void setAndBroadcastNetworkSetTimeZone(String zoneId) { + AlarmManager alarm = + (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE); + alarm.setTimeZone(zoneId); + Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE); + intent.putExtra("time-zone", zoneId); + phone.getContext().sendStickyBroadcast(intent); + } + + /** + * Set the time and Send out a sticky broadcast so the system can determine + * if the time was set by the carrier. + * + * @param time time set by network + */ + private void setAndBroadcastNetworkSetTime(long time) { + SystemClock.setCurrentTimeMillis(time); + Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME); + intent.putExtra("time", time); + phone.getContext().sendStickyBroadcast(intent); + } + + private void revertToNitz() { + if (Settings.System.getInt(phone.getContext().getContentResolver(), + Settings.System.AUTO_TIME, 0) == 0) { + return; + } + Log.d(LOG_TAG, "Reverting to NITZ: tz='" + mSavedTimeZone + + "' mSavedTime=" + mSavedTime + + " mSavedAtTime=" + mSavedAtTime); + if (mSavedTimeZone != null && mSavedTime != 0 && mSavedAtTime != 0) { + setAndBroadcastNetworkSetTimeZone(mSavedTimeZone); + setAndBroadcastNetworkSetTime(mSavedTime + + (SystemClock.elapsedRealtime() - mSavedAtTime)); + } + } + /** * @return true if phone is camping on a technology * that could support voice and data simultaneously. diff --git a/telephony/java/com/android/internal/telephony/cdma/FeatureCode.java b/telephony/java/com/android/internal/telephony/cdma/FeatureCode.java index c226b62eef439..85fe6dc486583 100644 --- a/telephony/java/com/android/internal/telephony/cdma/FeatureCode.java +++ b/telephony/java/com/android/internal/telephony/cdma/FeatureCode.java @@ -84,7 +84,7 @@ public final class FeatureCode extends Handler implements MmiCode { CDMAPhone phone; Context context; - + CdmaConnection suppConn; String action; // '*' in CDMA String sc; // Service Code String poundString; // Entire Flash string @@ -239,8 +239,15 @@ public final class FeatureCode extends Handler implements MmiCode { /** Process a Flash Code...anything that isn't a dialing number */ void processCode () { Log.d(LOG_TAG, "send feature code..."); - phone.mCM.sendCDMAFeatureCode(this.poundString, - obtainMessage(EVENT_CDMA_FLASH_COMPLETED)); + if (this.poundString != null) { + // TODO(Moto): Is suppConn going away? + suppConn = new CdmaConnection(phone.getContext(), this.poundString, phone.mCT, null); + phone.mCM.sendCDMAFeatureCode(suppConn.address, + obtainMessage(EVENT_CDMA_FLASH_COMPLETED)); + } else { + phone.mCM.sendCDMAFeatureCode(this.poundString, + obtainMessage(EVENT_CDMA_FLASH_COMPLETED)); + } } /** Called from CDMAPhone.handleMessage; not a Handler subclass */ @@ -261,6 +268,7 @@ public final class FeatureCode extends Handler implements MmiCode { } else { state = State.COMPLETE; message = context.getText(com.android.internal.R.string.fcComplete); + suppConn.processNextPostDialChar(); } phone.onFeatureCodeDone(this); break; diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java index 321824fbce249..d5b83793a7771 100644 --- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java +++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java @@ -39,6 +39,10 @@ import com.android.internal.telephony.IccRecords; import com.android.internal.telephony.IccUtils; import com.android.internal.telephony.PhoneProxy; +import com.android.internal.telephony.TelephonyIntents; +import android.app.ActivityManagerNative; +import android.content.Intent; + /** * {@hide} @@ -47,6 +51,7 @@ public final class RuimRecords extends IccRecords { static final String LOG_TAG = "CDMA"; private static final boolean DBG = true; + private boolean m_ota_commited=false; //***** Instance Variables @@ -73,6 +78,7 @@ public final class RuimRecords extends IccRecords { private static final int EVENT_GET_SMS_DONE = 22; private static final int EVENT_RUIM_REFRESH = 31; + private static final int EVENT_OTA_PROVISION_STATUS_CHANGE = 32; RuimRecords(CDMAPhone p) { super(p); @@ -93,6 +99,7 @@ public final class RuimRecords extends IccRecords { // Start off by setting empty state onRadioOffOrNotAvailable(); + p.mCM.registerForCdmaOtaProvision(this,EVENT_OTA_PROVISION_STATUS_CHANGE, null); } @@ -101,6 +108,8 @@ public final class RuimRecords extends IccRecords { phone.mCM.unregisterForRUIMReady(this); phone.mCM.unregisterForOffOrNotAvailable( this); phone.mCM.unSetOnIccRefresh(this); + phone.mCM.unregisterForNVReady(this); + phone.mCM.unregisterForCdmaOtaProvision(this); } @Override @@ -134,7 +143,7 @@ public final class RuimRecords extends IccRecords { return mMyMobileNumber; } - public String getMin() { + public String getCdmaMin() { return mMin2Min1; } @@ -219,11 +228,21 @@ public final class RuimRecords extends IccRecords { if (ar.exception != null) { break; } - + if(m_ota_commited) { + if(mMyMobileNumber != localTemp[0]) { + Intent intent = new Intent(TelephonyIntents.ACTION_CDMA_OTA_MDN_CHANGED); + intent.putExtra("mdn", localTemp[0]); + Log.d(LOG_TAG,"Broadcasting intent MDN Change in OTA "); + ActivityManagerNative.broadcastStickyIntent(intent, null); + } + m_ota_commited=false; + } mMyMobileNumber = localTemp[0]; mSid = localTemp[1]; mNid = localTemp[2]; - mMin2Min1 = localTemp[3]; + if (localTemp.length >= 3) { // TODO(Moto): remove when new ril always returns min2_min1 + mMin2Min1 = localTemp[3]; + } Log.d(LOG_TAG, "MDN: " + mMyMobileNumber + " MIN: " + mMin2Min1); @@ -272,6 +291,19 @@ public final class RuimRecords extends IccRecords { } break; + case EVENT_OTA_PROVISION_STATUS_CHANGE: + m_ota_commited=false; + ar = (AsyncResult)msg.obj; + if (ar.exception == null) { + int[] ints = (int[]) ar.result; + int otaStatus = ints[0]; + if (otaStatus== phone.CDMA_OTA_PROVISION_STATUS_COMMITTED) { + m_ota_commited=true; + phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE)); + } + } + break; + }}catch (RuntimeException exc) { // I don't want these exceptions to be fatal Log.w(LOG_TAG, "Exception parsing RUIM record", exc); @@ -374,17 +406,17 @@ public final class RuimRecords extends IccRecords { switch ((result[0])) { case CommandsInterface.SIM_REFRESH_FILE_UPDATED: - if (DBG) log("handleRuimRefresh with SIM_REFRESH_FILE_UPDATED"); + if (DBG) log("handleRuimRefresh with SIM_REFRESH_FILE_UPDATED"); adnCache.reset(); fetchRuimRecords(); break; case CommandsInterface.SIM_REFRESH_INIT: - if (DBG) log("handleRuimRefresh with SIM_REFRESH_INIT"); + if (DBG) log("handleRuimRefresh with SIM_REFRESH_INIT"); // need to reload all files (that we care about) fetchRuimRecords(); break; case CommandsInterface.SIM_REFRESH_RESET: - if (DBG) log("handleRuimRefresh with SIM_REFRESH_RESET"); + if (DBG) log("handleRuimRefresh with SIM_REFRESH_RESET"); phone.mCM.setRadioPower(false, null); /* Note: no need to call setRadioPower(true). Assuming the desired * radio power state is still ON (as tracked by ServiceStateTracker), @@ -396,7 +428,7 @@ public final class RuimRecords extends IccRecords { break; default: // unknown refresh operation - if (DBG) log("handleRuimRefresh with unknown operation"); + if (DBG) log("handleRuimRefresh with unknown operation"); break; } } diff --git a/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java b/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java new file mode 100644 index 0000000000000..444dec31b1ff0 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony.cdma; + +import java.util.HashMap; +import java.util.HashSet; +import android.util.Log; +import android.media.ToneGenerator; + +public class SignalToneUtil { + // public final int int IS95_CONST_IR_SIGNAL_TYPE_TYPE; + static public final int IS95_CONST_IR_SIGNAL_TONE = 0; + static public final int IS95_CONST_IR_SIGNAL_ISDN = 1; + static public final int IS95_CONST_IR_SIGNAL_IS54B = 2; + static public final int IS95_CONST_IR_SIGNAL_USR_DEFD_ALERT = 4; + + // public final int int IS95_CONST_IR_ALERT_PITCH_TYPE; + static public final int IS95_CONST_IR_ALERT_MED = 0; + static public final int IS95_CONST_IR_ALERT_HIGH = 1; + static public final int IS95_CONST_IR_ALERT_LOW = 2; + static public final int TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN = 255; + + // public final int int IS95_CONST_IR_SIGNAL_TYPE; + static public final int IS95_CONST_IR_SIG_ISDN_NORMAL = 0; + static public final int IS95_CONST_IR_SIG_ISDN_INTGRP = 1; + static public final int IS95_CONST_IR_SIG_ISDN_SP_PRI = 2; + static public final int IS95_CONST_IR_SIG_ISDN_PAT_3 = 3; + static public final int IS95_CONST_IR_SIG_ISDN_PING = 4; + static public final int IS95_CONST_IR_SIG_ISDN_PAT_5 = 5; + static public final int IS95_CONST_IR_SIG_ISDN_PAT_6 = 6; + static public final int IS95_CONST_IR_SIG_ISDN_PAT_7 = 7; + static public final int IS95_CONST_IR_SIG_ISDN_OFF = 15; + static public final int IS95_CONST_IR_SIG_TONE_DIAL = 0; + static public final int IS95_CONST_IR_SIG_TONE_RING = 1; + static public final int IS95_CONST_IR_SIG_TONE_INT = 2; + static public final int IS95_CONST_IR_SIG_TONE_ABB_INT = 3; + static public final int IS95_CONST_IR_SIG_TONE_REORDER = 4; + static public final int IS95_CONST_IR_SIG_TONE_ABB_RE = 5; + static public final int IS95_CONST_IR_SIG_TONE_BUSY = 6; + static public final int IS95_CONST_IR_SIG_TONE_CONFIRM = 7; + static public final int IS95_CONST_IR_SIG_TONE_ANSWER = 8; + static public final int IS95_CONST_IR_SIG_TONE_CALL_W = 9; + static public final int IS95_CONST_IR_SIG_TONE_PIP = 10; + static public final int IS95_CONST_IR_SIG_TONE_NO_TONE = 63; + static public final int IS95_CONST_IR_SIG_IS54B_NO_TONE = 0; + static public final int IS95_CONST_IR_SIG_IS54B_L = 1; + static public final int IS95_CONST_IR_SIG_IS54B_SS = 2; + static public final int IS95_CONST_IR_SIG_IS54B_SSL = 3; + static public final int IS95_CONST_IR_SIG_IS54B_SS_2 = 4; + static public final int IS95_CONST_IR_SIG_IS54B_SLS = 5; + static public final int IS95_CONST_IR_SIG_IS54B_S_X4 = 6; + static public final int IS95_CONST_IR_SIG_IS54B_PBX_L = 7; + static public final int IS95_CONST_IR_SIG_IS54B_PBX_SS = 8; + static public final int IS95_CONST_IR_SIG_IS54B_PBX_SSL = 9; + static public final int IS95_CONST_IR_SIG_IS54B_PBX_SLS = 10; + static public final int IS95_CONST_IR_SIG_IS54B_PBX_S_X4 = 11; + static public final int IS95_CONST_IR_SIG_TONE_ABBR_ALRT = 0; + + // Hashmap to map signalInfo To AudioTone + static private HashMap hm = new HashMap(); + + private static Integer signalParamHash(int signalType, int alertPitch, int signal) { + // TODO(Moto): The input should get checked before usage + return new Integer(signalType * 256 * 256 + alertPitch * 256 + signal); + } + + public static int getAudioToneFromSignalInfo(int signalType, int alertPitch, int signal) { + int result = ToneGenerator.TONE_CDMA_INVALID; + result = hm.get(signalParamHash(signalType, alertPitch, signal)); + return result; + } + + static { + + /* SIGNAL_TYPE_ISDN */ + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_ISDN_NORMAL), ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_ISDN_INTGRP), + ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_ISDN_SP_PRI), ToneGenerator.TONE_CDMA_CALL_SIGNAL_SP_PRI); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_ISDN_PAT_3), ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_PAT3); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_ISDN_PING), ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_RING_RING); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_ISDN_PAT_5), ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_PAT5); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_ISDN_PAT_6), ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_PAT6); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_ISDN_PAT_7), ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_PAT7); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_ISDN_OFF), ToneGenerator.TONE_CDMA_SIGNAL_OFF); + + /* SIGNAL_TYPE_TONE */ + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_TONE_DIAL), ToneGenerator.TONE_CDMA_DIAL_TONE_LITE); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_TONE_RING), ToneGenerator.TONE_CDMA_NETWORK_USA_RINGBACK); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_TONE_INT), ToneGenerator.TONE_SUP_INTERCEPT); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_TONE_ABB_INT), ToneGenerator.TONE_SUP_INTERCEPT_ABBREV); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_TONE_REORDER), ToneGenerator.TONE_CDMA_REORDER); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_TONE_ABB_RE), ToneGenerator.TONE_CDMA_ABBR_REORDER); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_TONE_BUSY), ToneGenerator.TONE_CDMA_NETWORK_BUSY); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_TONE_CONFIRM), ToneGenerator.TONE_SUP_CONFIRM); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_TONE_ANSWER), ToneGenerator.TONE_CDMA_ANSWER); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_TONE_ABB_RE), ToneGenerator.TONE_CDMA_NETWORK_CALLWAITING); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_TONE_PIP), ToneGenerator.TONE_CDMA_PIP); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_TONE_NO_TONE), ToneGenerator.TONE_CDMA_SIGNAL_OFF); + + /* SIGNAL_TYPE_IS54B */ + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_HIGH, + IS95_CONST_IR_SIG_IS54B_L), ToneGenerator.TONE_CDMA_HIGH_L); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_MED, + IS95_CONST_IR_SIG_IS54B_L), ToneGenerator.TONE_CDMA_INVALID); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_LOW, + IS95_CONST_IR_SIG_IS54B_L), ToneGenerator.TONE_CDMA_LOW_L); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_HIGH, + IS95_CONST_IR_SIG_IS54B_SS), ToneGenerator.TONE_CDMA_HIGH_SS); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_MED, + IS95_CONST_IR_SIG_IS54B_SS), ToneGenerator.TONE_CDMA_MED_SS); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_LOW, + IS95_CONST_IR_SIG_IS54B_SS), ToneGenerator.TONE_CDMA_LOW_SS); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_HIGH, + IS95_CONST_IR_SIG_IS54B_SSL), ToneGenerator.TONE_CDMA_HIGH_SSL); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_MED, + IS95_CONST_IR_SIG_IS54B_SSL), ToneGenerator.TONE_CDMA_MED_SSL); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_LOW, + IS95_CONST_IR_SIG_IS54B_SSL), ToneGenerator.TONE_CDMA_LOW_SSL); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_HIGH, + IS95_CONST_IR_SIG_IS54B_SS_2), ToneGenerator.TONE_CDMA_HIGH_SS_2); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_MED, + IS95_CONST_IR_SIG_IS54B_SS_2), ToneGenerator.TONE_CDMA_MED_SS_2); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_LOW, + IS95_CONST_IR_SIG_IS54B_SS_2), ToneGenerator.TONE_CDMA_LOW_SS_2); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_HIGH, + IS95_CONST_IR_SIG_IS54B_SLS), ToneGenerator.TONE_CDMA_HIGH_SLS); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_MED, + IS95_CONST_IR_SIG_IS54B_SLS), ToneGenerator.TONE_CDMA_MED_SLS); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_LOW, + IS95_CONST_IR_SIG_IS54B_SLS), ToneGenerator.TONE_CDMA_LOW_SLS); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_HIGH, + IS95_CONST_IR_SIG_IS54B_S_X4), ToneGenerator.TONE_CDMA_HIGH_S_X4); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_MED, + IS95_CONST_IR_SIG_IS54B_S_X4), ToneGenerator.TONE_CDMA_MED_S_X4); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_LOW, + IS95_CONST_IR_SIG_IS54B_S_X4), ToneGenerator.TONE_CDMA_LOW_S_X4); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_HIGH, + IS95_CONST_IR_SIG_IS54B_PBX_L), ToneGenerator.TONE_CDMA_HIGH_PBX_L); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_MED, + IS95_CONST_IR_SIG_IS54B_PBX_L), ToneGenerator.TONE_CDMA_MED_PBX_L); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_LOW, + IS95_CONST_IR_SIG_IS54B_PBX_L), ToneGenerator.TONE_CDMA_LOW_PBX_L); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_HIGH, + IS95_CONST_IR_SIG_IS54B_PBX_SS), ToneGenerator.TONE_CDMA_HIGH_PBX_SS); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_MED, + IS95_CONST_IR_SIG_IS54B_PBX_SS), ToneGenerator.TONE_CDMA_MED_PBX_SS); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_LOW, + IS95_CONST_IR_SIG_IS54B_PBX_SS), ToneGenerator.TONE_CDMA_LOW_PBX_SS); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_HIGH, + IS95_CONST_IR_SIG_IS54B_PBX_SSL), ToneGenerator.TONE_CDMA_HIGH_PBX_SSL); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_MED, + IS95_CONST_IR_SIG_IS54B_PBX_SSL), ToneGenerator.TONE_CDMA_MED_PBX_SSL); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_LOW, + IS95_CONST_IR_SIG_IS54B_PBX_SSL), ToneGenerator.TONE_CDMA_LOW_PBX_SSL); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_HIGH, + IS95_CONST_IR_SIG_IS54B_PBX_SLS), ToneGenerator.TONE_CDMA_HIGH_PBX_SLS); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_MED, + IS95_CONST_IR_SIG_IS54B_PBX_SLS), ToneGenerator.TONE_CDMA_MED_PBX_SLS); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_LOW, + IS95_CONST_IR_SIG_IS54B_PBX_SLS), ToneGenerator.TONE_CDMA_LOW_PBX_SLS); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_HIGH, + IS95_CONST_IR_SIG_IS54B_PBX_S_X4), ToneGenerator.TONE_CDMA_HIGH_PBX_S_X4); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_MED, + IS95_CONST_IR_SIG_IS54B_PBX_S_X4), ToneGenerator.TONE_CDMA_MED_PBX_S_X4); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_LOW, + IS95_CONST_IR_SIG_IS54B_PBX_S_X4), ToneGenerator.TONE_CDMA_LOW_PBX_S_X4); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, + IS95_CONST_IR_SIG_IS54B_NO_TONE), ToneGenerator.TONE_CDMA_SIGNAL_OFF); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_USR_DEFD_ALERT, + TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, IS95_CONST_IR_SIG_TONE_ABBR_ALRT), + ToneGenerator.TONE_CDMA_ABBR_ALERT); + + hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_USR_DEFD_ALERT, + TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN, IS95_CONST_IR_SIG_TONE_NO_TONE), + ToneGenerator.TONE_CDMA_ABBR_ALERT); + + } + + // suppress default constructor for noninstantiability + private SignalToneUtil() { + } +} diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java index 3459dcdf23865..70d71fc83f443 100755 --- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java +++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java @@ -878,11 +878,6 @@ public class GSMPhone extends PhoneBase { return ret; } - public String getMin() { - Log.e(LOG_TAG, "[GSMPhone] getMin() is a CDMA method"); - return "0"; - } - public String getDeviceId() { return mImei; } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java index 699142a28aca8..8bf5d1903cb5a 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java @@ -22,12 +22,14 @@ import android.app.PendingIntent.CanceledException; import android.content.Intent; import android.os.AsyncResult; import android.os.Message; +import android.provider.Telephony.Sms.Intents; import android.telephony.ServiceState; import android.util.Config; import android.util.Log; import com.android.internal.telephony.IccUtils; import com.android.internal.telephony.gsm.SmsMessage; +import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.SMSDispatcher; import com.android.internal.telephony.SmsHeader; import com.android.internal.telephony.SmsMessageBase; @@ -78,7 +80,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } if (mCm != null) { - mCm.acknowledgeLastIncomingSMS(true, null); + mCm.acknowledgeLastIncomingGsmSms(true, Intents.RESULT_SMS_HANDLED, null); } } @@ -150,7 +152,13 @@ final class GsmSMSDispatcher extends SMSDispatcher { concatRef.refNumber = refNumber; concatRef.seqNumber = i + 1; // 1-based sequence concatRef.msgCount = msgCount; - concatRef.isEightBits = false; + // TODO: We currently set this to true since our messaging app will never + // send more than 255 parts (it converts the message to MMS well before that). + // However, we should support 3rd party messaging apps that might need 16-bit + // references + // Note: It's not sufficient to just flip this bit to true; it will have + // ripple effects (several calculations assume 8-bit ref). + concatRef.isEightBits = true; SmsHeader smsHeader = new SmsHeader(); smsHeader.concatRef = concatRef; @@ -284,10 +292,10 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ - protected void acknowledgeLastIncomingSms(boolean success, Message response){ + protected void acknowledgeLastIncomingSms(boolean success, int result, Message response){ // FIXME unit test leaves cm == null. this should change if (mCm != null) { - mCm.acknowledgeLastIncomingSMS(success, response); + mCm.acknowledgeLastIncomingGsmSms(success, resultToCause(result), response); } } @@ -312,4 +320,17 @@ final class GsmSMSDispatcher extends SMSDispatcher { response.recycle(); } + private int resultToCause(int rc) { + switch (rc) { + case Activity.RESULT_OK: + case Intents.RESULT_SMS_HANDLED: + // Cause code is ignored on success. + return 0; + case Intents.RESULT_SMS_OUT_OF_MEMORY: + return CommandsInterface.GSM_SMS_FAIL_CAUSE_MEMORY_CAPACITY_EXCEEDED; + case Intents.RESULT_SMS_GENERIC_ERROR: + default: + return CommandsInterface.GSM_SMS_FAIL_CAUSE_UNSPECIFIED_ERROR; + } + } } diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java index 42bb2e0c33768..9fb9be82b4602 100644 --- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java +++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java @@ -1018,6 +1018,10 @@ public final class SimulatedCommands extends BaseCommands unimplemented(result); } + public void reportSmsMemoryStatus(boolean available, Message result) { + unimplemented(result); + } + private boolean isSimLocked() { if (mSimLockedState != SimLockState.NONE) { return true; @@ -1041,11 +1045,11 @@ public final class SimulatedCommands extends BaseCommands } - public void acknowledgeLastIncomingSMS(boolean success, Message result) { + public void acknowledgeLastIncomingGsmSms(boolean success, int cause, Message result) { unimplemented(result); } - public void acknowledgeLastIncomingCdmaSms(boolean success, Message result) { + public void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) { unimplemented(result); } @@ -1137,7 +1141,7 @@ public final class SimulatedCommands extends BaseCommands String number, Message result) {unimplemented(result);} public void setNetworkSelectionModeAutomatic(Message result) {unimplemented(result);} - + public void exitEmergencyCallbackMode(Message result) {unimplemented(result);} public void setNetworkSelectionModeManual( String operatorNumeric, Message result) {unimplemented(result);} @@ -1460,10 +1464,6 @@ public final class SimulatedCommands extends BaseCommands } - public void exitEmergencyCallbackMode(Message response) { - // TODO method stub - } - public void forceDataDormancy(Message response) { // TODO method stub } diff --git a/test-runner/android/test/InstrumentationTestRunner.java b/test-runner/android/test/InstrumentationTestRunner.java index d5e64596c7319..6658fb0732130 100644 --- a/test-runner/android/test/InstrumentationTestRunner.java +++ b/test-runner/android/test/InstrumentationTestRunner.java @@ -118,7 +118,8 @@ import java.util.List; * To generate EMMA code coverage: * -e coverage true * Note: this requires an emma instrumented build. By default, the code coverage results file - * will be saved as /sdcard/coverage.ec, unless overridden by coverageFile flag (see below) + * will be saved in a /data//coverage.ec file, unless overridden by coverageFile flag (see + * below) *

      * To specify EMMA code coverage results file path: * -e coverageFile /sdcard/myFile.ec @@ -217,6 +218,11 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu * reports the guessed suite assignment for the current test. */ private static final String REPORT_KEY_SUITE_ASSIGNMENT = "suiteassignment"; + /** + * If included in the status or final bundle sent to an IInstrumentationWatcher, this key + * identifies the path to the generated code coverage file. + */ + private static final String REPORT_KEY_COVERAGE_PATH = "coverageFilePath"; /** * The test is starting. */ @@ -240,7 +246,8 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu */ public static final String REPORT_KEY_STACK = "stack"; - private static final String DEFAULT_COVERAGE_FILE_PATH = "/sdcard/coverage.ec"; + // Default file name for code coverage + private static final String DEFAULT_COVERAGE_FILE_NAME = "coverage.ec"; private static final String LOG_TAG = "InstrumentationTestRunner"; @@ -456,14 +463,20 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu private void generateCoverageReport() { // use reflection to call emma dump coverage method, to avoid // always statically compiling against emma jar - java.io.File coverageFile = new java.io.File(getCoverageFilePath()); + String coverageFilePath = getCoverageFilePath(); + java.io.File coverageFile = new java.io.File(coverageFilePath); try { Class emmaRTClass = Class.forName("com.vladium.emma.rt.RT"); Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData", coverageFile.getClass(), boolean.class, boolean.class); dumpCoverageMethod.invoke(null, coverageFile, false, false); - + // output path to generated coverage file so it can be parsed by a test harness if + // needed + mResults.putString(REPORT_KEY_COVERAGE_PATH, coverageFilePath); + // also output a more user friendly msg + mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT, + String.format("Generated code coverage data to %s", coverageFilePath)); } catch (ClassNotFoundException e) { reportEmmaError("Is emma jar on classpath?", e); } catch (SecurityException e) { @@ -481,8 +494,9 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu private String getCoverageFilePath() { if (mCoverageFilePath == null) { - return DEFAULT_COVERAGE_FILE_PATH; - } + return getTargetContext().getFilesDir().getAbsolutePath() + File.separator + + DEFAULT_COVERAGE_FILE_NAME; + } else { return mCoverageFilePath; } diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java index 508afcf411b81..5161f7beda0e4 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java @@ -17,16 +17,17 @@ package com.android.unit_tests.os; import android.os.MemoryFile; +import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; -import junit.framework.TestCase; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.IOException; - -import java.util.List; import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; public class MemoryFileTest extends TestCase { @@ -94,6 +95,74 @@ public class MemoryFileTest extends TestCase { file.close(); } + // Tests that close() is idempotent + @SmallTest + public void testCloseClose() throws Exception { + MemoryFile file = new MemoryFile("MemoryFileTest", 1000000); + byte[] data = new byte[512]; + file.writeBytes(data, 0, 0, 128); + file.close(); + file.close(); + } + + // Tests that we can't read from a closed memory file + @SmallTest + public void testCloseRead() throws Exception { + MemoryFile file = new MemoryFile("MemoryFileTest", 1000000); + file.close(); + + try { + byte[] data = new byte[512]; + assertEquals(128, file.readBytes(data, 0, 0, 128)); + fail("readBytes() after close() did not throw IOException."); + } catch (IOException e) { + // this is what should happen + } + } + + // Tests that we can't write to a closed memory file + @SmallTest + public void testCloseWrite() throws Exception { + MemoryFile file = new MemoryFile("MemoryFileTest", 1000000); + file.close(); + + try { + byte[] data = new byte[512]; + file.writeBytes(data, 0, 0, 128); + fail("writeBytes() after close() did not throw IOException."); + } catch (IOException e) { + // this is what should happen + } + } + + // Tests that we can't call allowPurging() after close() + @SmallTest + public void testCloseAllowPurging() throws Exception { + MemoryFile file = new MemoryFile("MemoryFileTest", 1000000); + byte[] data = new byte[512]; + file.writeBytes(data, 0, 0, 128); + file.close(); + + try { + file.allowPurging(true); + fail("allowPurging() after close() did not throw IOException."); + } catch (IOException e) { + // this is what should happen + } + } + + // Tests that we don't leak file descriptors or mmap areas + @LargeTest + public void testCloseLeak() throws Exception { + // open enough memory files that we should run out of + // file descriptors or address space if we leak either. + for (int i = 0; i < 1025; i++) { + MemoryFile file = new MemoryFile("MemoryFileTest", 5000000); + file.writeBytes(testString, 0, 0, testString.length); + file.close(); + } + } + private static final byte[] testString = new byte[] { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8, 3, 2, 7, 9, 5, 0, 2, 8, 8, 4, 1, 9, 7, 1, 6, 9, 3, 9, 9, 3, 7, 5, 1, 0, 5, 8, 2, 0, 9, 7, 4, 9, 4, 4, 5, 9, 2, 3, 0, 7, 8, 1, 6, 4, 0, 6, 2, 8, 6, 2, 0, 8, 9, 9, 8, 6, 2, 8, 0, 3, 4, 8, 2, 5, 3, 4, 2, 1, 1, 7, 0, 6, 7, 9, 8, 2, 1, 4, 8, 0, 8, 6, 5, 1, 3, 2, 8, 2, 3, 0, 6, 6, 4, 7, 0, 9, 3, 8, 4, 4, 6, 0, 9, 5, 5, 0, 5, 8, 2, 2, 3, 1, 7, 2, diff --git a/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java b/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java index e2336f8832c99..3a9c5116f1605 100644 --- a/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java +++ b/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java @@ -41,7 +41,7 @@ public class GsmAlphabetTest extends TestCase { SmsHeader.toByteArray(header)); int septetCount = GsmAlphabet.countGsmSeptets(message, false); String parsedMessage = GsmAlphabet.gsm7BitPackedToString( - userData, SmsHeader.toByteArray(header).length+1, septetCount, 1); + userData, SmsHeader.toByteArray(header).length+2, septetCount, 1); assertEquals(message, parsedMessage); } diff --git a/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java b/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java index 6767de632d839..7865a5c750b6b 100644 --- a/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java +++ b/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java @@ -33,6 +33,7 @@ import android.gesture.Gesture; import android.gesture.GestureOverlayView; import android.gesture.LetterRecognizer; import android.gesture.Prediction; +import android.gesture.LetterRecognizers; import java.util.ArrayList; @@ -57,8 +58,8 @@ public class ContactListGestureOverlay extends Activity { setContentView(R.layout.overlaydemo); // create a letter recognizer - mRecognizer = LetterRecognizer.getLetterRecognizer(this, - LetterRecognizer.RECOGNIZER_LATIN_LOWERCASE); + mRecognizer = LetterRecognizers.fromType(this, + LetterRecognizers.RECOGNIZER_LATIN_LOWERCASE); mOverlay = (GestureOverlayView) findViewById(R.id.overlay); // load the contact list diff --git a/tests/sketch/src/com/android/gesture/example/GestureEntry.java b/tests/sketch/src/com/android/gesture/example/GestureEntry.java index 3f86ed4857a9c..8dbec998cecd3 100644 --- a/tests/sketch/src/com/android/gesture/example/GestureEntry.java +++ b/tests/sketch/src/com/android/gesture/example/GestureEntry.java @@ -36,9 +36,10 @@ import android.widget.Spinner; import android.widget.AdapterView.OnItemSelectedListener; import android.gesture.Gesture; -import android.gesture.GestureLibrary; import android.gesture.GestureOverlayView; import android.gesture.Prediction; +import android.gesture.GestureLibraries; +import android.gesture.GestureLibrary; import java.io.File; import java.util.ArrayList; @@ -61,7 +62,7 @@ public class GestureEntry extends Activity { private Spinner mRecognitionResult; - private GestureLibrary mGestureLibrary; + private GestureLibrary mGestureStore; private boolean mChangedByRecognizer = false; @@ -71,8 +72,8 @@ public class GestureEntry extends Activity { setContentView(R.layout.demo); // init the gesture library - mGestureLibrary = new GestureLibrary(GESTURE_FILE_NAME); - mGestureLibrary.load(); + mGestureStore = GestureLibraries.fromFile(GESTURE_FILE_NAME); + mGestureStore.load(); // create the spinner for showing the recognition results // the spinner also allows a user to correct a prediction @@ -82,7 +83,7 @@ public class GestureEntry extends Activity { public void onItemSelected(AdapterView parent, View view, int position, long id) { // correct the recognition result by adding the new example if (!mChangedByRecognizer) { - mGestureLibrary.addGesture(parent.getSelectedItem().toString(), mGesturePad + mGestureStore.addGesture(parent.getSelectedItem().toString(), mGesturePad .getGesture()); } else { mChangedByRecognizer = false; @@ -109,7 +110,7 @@ public class GestureEntry extends Activity { public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) { overlay.clear(false); } - + public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) { } }); @@ -134,7 +135,7 @@ public class GestureEntry extends Activity { .findViewById(R.id.gesturename_edit); String text = edittext.getText().toString().trim(); if (text.length() > 0) { - mGestureLibrary.addGesture(text, mGesturePad.getGesture()); + mGestureStore.addGesture(text, mGesturePad.getGesture()); } } }).setNegativeButton(R.string.newgesture_dialog_cancel, @@ -173,14 +174,14 @@ public class GestureEntry extends Activity { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - mGestureLibrary.load(); + mGestureStore.load(); mGesturePad.clear(false); } @Override protected void onPause() { super.onPause(); - mGestureLibrary.save(); + mGestureStore.save(); } @Override @@ -195,12 +196,12 @@ public class GestureEntry extends Activity { if (gesture != null) { outState.putParcelable(PARCEL_KEY, gesture); } - mGestureLibrary.save(); + mGestureStore.save(); } private void recognize(Gesture gesture) { mChangedByRecognizer = true; - ArrayList predictions = mGestureLibrary.recognize(gesture); + ArrayList predictions = mGestureStore.recognize(gesture); ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, predictions); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); diff --git a/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java index a561c9640889b..f5bf683513383 100755 --- a/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java +++ b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java @@ -28,8 +28,9 @@ import android.widget.Spinner; import android.widget.AdapterView.OnItemSelectedListener; import android.gesture.Gesture; -import android.gesture.GestureLibrary; import android.gesture.GestureOverlayView; +import android.gesture.GestureLibraries; +import android.gesture.GestureLibrary; import java.util.ArrayList; import java.util.Collections; @@ -45,7 +46,7 @@ public class GestureLibViewer extends Activity { private Spinner mGestureCategory; - private GestureLibrary mGesureLibrary; + private GestureLibrary mGesureStore; private ArrayList mGestures; @@ -59,15 +60,15 @@ public class GestureLibViewer extends Activity { String name = (String) mGestureCategory.getSelectedItem(); Gesture gesture = mGestures.get(mCurrentGestureIndex); - mGesureLibrary.removeGesture(name, gesture); + mGesureStore.removeGesture(name, gesture); - mGestures = mGesureLibrary.getGestures(name); + mGestures = mGesureStore.getGestures(name); if (mGestures == null) { // delete the entire entry mCurrentGestureIndex = 0; ArrayList list = new ArrayList(); - list.addAll(mGesureLibrary.getGestureEntries()); + list.addAll(mGesureStore.getGestureEntries()); Collections.sort(list); ArrayAdapter adapter = new ArrayAdapter(GestureLibViewer.this, android.R.layout.simple_spinner_item, list); @@ -83,7 +84,7 @@ public class GestureLibViewer extends Activity { } } } - + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -94,19 +95,19 @@ public class GestureLibViewer extends Activity { mGesturePad.setEnabled(false); // init the gesture library - mGesureLibrary = new GestureLibrary(GestureEntry.GESTURE_FILE_NAME); - mGesureLibrary.load(); + mGesureStore = GestureLibraries.fromFile(GestureEntry.GESTURE_FILE_NAME); + mGesureStore.load(); mGestureCategory = (Spinner) findViewById(R.id.spinner); ArrayList list = new ArrayList(); - if (!mGesureLibrary.getGestureEntries().isEmpty()) { - list.addAll(mGesureLibrary.getGestureEntries()); + if (!mGesureStore.getGestureEntries().isEmpty()) { + list.addAll(mGesureStore.getGestureEntries()); Collections.sort(list); ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, list); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mGestureCategory.setAdapter(adapter); - mGestures = mGesureLibrary.getGestures(list.get(0)); + mGestures = mGesureStore.getGestures(list.get(0)); mCurrentGestureIndex = 0; Gesture gesture = mGestures.get(mCurrentGestureIndex); mGesturePad.setGesture(gesture); @@ -114,7 +115,7 @@ public class GestureLibViewer extends Activity { mGestureCategory.setOnItemSelectedListener(new OnItemSelectedListener() { public void onItemSelected(AdapterView parent, View view, int position, long id) { - mGestures = mGesureLibrary.getGestures((String) mGestureCategory.getSelectedItem()); + mGestures = mGesureStore.getGestures((String) mGestureCategory.getSelectedItem()); if (!mGestures.isEmpty()) { mCurrentGestureIndex = 0; Gesture gesture = mGestures.get(mCurrentGestureIndex); @@ -160,7 +161,7 @@ public class GestureLibViewer extends Activity { @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { - mGesureLibrary.save(); + mGesureStore.save(); setResult(RESULT_OK); finish(); return true; @@ -172,12 +173,12 @@ public class GestureLibViewer extends Activity { @Override protected void onPause() { super.onPause(); - mGesureLibrary.save(); + mGesureStore.save(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - mGesureLibrary.save(); + mGesureStore.save(); } } diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 0db868e4fbd6b..c31577cd06b1c 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -72,8 +72,8 @@ interface IWifiManager boolean isMulticastEnabled(); - void enableMulticast(IBinder binder, String tag); + void acquireMulticastLock(IBinder binder, String tag); - void disableMulticast(); + void releaseMulticastLock(); } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 141d53f71b013..c4dff6a1ff509 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -825,6 +825,117 @@ public class WifiManager { return new WifiLock(WIFI_MODE_FULL, tag); } + + /** + * Create a new MulticastLock + * + * @param tag a tag for the MulticastLock to identify it in debugging + * messages. + * + * @return a new, unacquired MulticastLock with the given tag. + * + * @see MulticastLock + */ + public MulticastLock createMulticastLock(String tag) { + return new MulticastLock(tag); + } + + /** + * Allows an application to receive Wifi Multicast packets. + * Normally the Wifi stack filters out packets not explicitly + * addressed to this device. Acquring a MulticastLock will + * cause the stack to receive packets addressed to multicast + * addresses. Processing these extra packets can cause a noticable + * battery drain and should be disabled when not needed + */ + public class MulticastLock { + private String mTag; + private final IBinder mBinder; + private boolean mHeld; + + private MulticastLock(String tag) { + mTag = tag; + mBinder = new Binder(); + mHeld = false; + } + + /** + * Locks Wifi Multicast on until {@link #release} is called. + * + * The first call to {@code acquire} will lock the Multicast on + * but subsequent calls will be ignored. Only one call to + * {@link #release} will be required, regardless of the number of + * times that {@code acquire} is called. + * + * Note that other applications may also lock Wifi Multicast on. + * Only they can relinquish their lock. + * + * Also note that applications cannot leave Multicast locked on. + * When an app exits or crashes, any Multicast locks will be released. + */ + public void acquire() { + synchronized (mBinder) { + if (!mHeld) { + try { + mService.acquireMulticastLock(mBinder, mTag); + mHeld = true; + } catch (RemoteException ignore) { + } + } + } + } + + /** + * Unlocks Wifi Multicast, restoring the filter of packets + * not addressed specifically to this device and saving power. + * + * Note that if any other Wifi Multicast Locks are still outstanding + * this {@code release} call will not have an immediate effect. Only + * when all applications have released all their Multicast Locks will + * the Multicast filter be turned back on. + * + * Also note that when an app exits or crashes all of its Multicast + * Locks will be automatically released. + */ + public void release() { + synchronized (mBinder) { + if (mHeld) { + try { + mService.releaseMulticastLock(); + mHeld = false; + } catch (RemoteException ignore) { + } + } + } + } + + /** + * Checks whether this MulticastLock is currently held. + * + * @return true if this MulticastLock is held, false otherwise + */ + public boolean isHeld() { + synchronized (mBinder) { + return mHeld; + } + } + + public String toString() { + String s1, s2; + synchronized (mBinder) { + s1 = Integer.toHexString(System.identityHashCode(this)); + s2 = mHeld ? "held; " : ""; + return "MulticastLock{ " + s1 + "; " + s2 + " }"; + } + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + release(); + } + } + /** * Check multicast filter status. * @@ -839,50 +950,4 @@ public class WifiManager { return false; } } - - /** - * Turn on the reception of multicast packets. - * The default behavior is to disable multicast packets as they - * have a noticable negative effect on battery life. An - * application can turn them on, but should not leave it on for longer - * than needed. When the app quits (or crashes) its request will - * be reverted. - * - * @param tag a string associated with this request for debugging. - * - * @return true on success - * - * @see #disableMulticast - * - * @hide pending API council approval - */ - public boolean enableMulticast(String tag) { - try { - mService.enableMulticast(new Binder(), tag); - return true; - } catch (RemoteException e) { - return false; - } - } - - /** - * Return to the default multicast-off setting. - * Note that if others had turned on Multicast reception, your - * call will not turn it back off - they must also turn off their - * request for multicast reception. - * - * @return true on success - * - * @see #enableMulticast - * - * @hide pending API council approval - */ - public boolean disableMulticast() { - try { - mService.disableMulticast(); - return true; - } catch (RemoteException e) { - return false; - } - } } diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java index 7ba124fda0e98..e6f413097999e 100644 --- a/wifi/java/android/net/wifi/WifiStateTracker.java +++ b/wifi/java/android/net/wifi/WifiStateTracker.java @@ -755,8 +755,10 @@ public class WifiStateTracker extends NetworkStateTracker { * first and then off.. if nobody else wants it on it'll be * off then and it's all synchronized within the API. */ - mWM.enableMulticast("WifiStateTracker"); - mWM.disableMulticast(); + WifiManager.MulticastLock l = + mWM.createMulticastLock("WifiStateTracker"); + l.acquire(); + l.release(); if (mBluetoothA2dp == null) { mBluetoothA2dp = new BluetoothA2dp(mContext);