Merge "CdmaLte: Use SPN from SIM card if SIM card is presend" into honeycomb-LTE
diff --git a/api/current.xml b/api/current.xml
index 83e571d..117ecf9 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1024,6 +1024,17 @@
visibility="public"
>
</field>
+<field name="SET_POINTER_SPEED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.permission.SET_POINTER_SPEED""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="SET_PREFERRED_APPLICATIONS"
type="java.lang.String"
transient="false"
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d69303e..eb9eb03 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1791,6 +1791,16 @@
public static final String SIP_ASK_ME_EACH_TIME = "SIP_ASK_ME_EACH_TIME";
/**
+ * Pointer speed setting.
+ * This is an integer value in a range between -7 and +7, so there are 15 possible values.
+ * -7 = slowest
+ * 0 = default speed
+ * +7 = fastest
+ * @hide
+ */
+ public static final String POINTER_SPEED = "pointer_speed";
+
+ /**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
* @hide
@@ -1854,6 +1864,7 @@
USE_PTP_INTERFACE,
SIP_CALL_OPTIONS,
SIP_RECEIVE_CALLS,
+ POINTER_SPEED,
};
// Settings moved to Settings.Secure
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 4427eb5..ad17edf 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -205,4 +205,9 @@
* Called by the status bar to notify Views of changes to System UI visiblity.
*/
void statusBarVisibilityChanged(int visibility);
+
+ /**
+ * Called by the settings application to temporarily set the pointer speed.
+ */
+ void setPointerSpeed(int speed);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index bb31347..4d40b57 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1082,6 +1082,13 @@
android:description="@string/permdesc_setOrientation"
android:protectionLevel="signature" />
+ <!-- Allows low-level access to setting the pointer speed.
+ Not for use by normal applications. -->
+ <permission android:name="android.permission.SET_POINTER_SPEED"
+ android:label="@string/permlab_setPointerSpeed"
+ android:description="@string/permdesc_setPointerSpeed"
+ android:protectionLevel="signature" />
+
<!-- Allows an application to install packages. -->
<permission android:name="android.permission.INSTALL_PACKAGES"
android:label="@string/permlab_installPackages"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a7d0d78..f7f2606 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -699,6 +699,13 @@
the rotation of the screen at any time. Should never be needed for
normal applications.</string>
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
+ <string name="permlab_setPointerSpeed">change pointer speed</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+ <string name="permdesc_setPointerSpeed">Allows an application to change
+ the mouse or trackpad pointer speed at any time. Should never be needed for
+ normal applications.</string>
+
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_signalPersistentProcesses">send Linux signals to applications</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/include/ui/Input.h b/include/ui/Input.h
index fb6152e..d603441 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -627,6 +627,87 @@
int32_t mActivePointerId;
};
+
+/*
+ * Specifies parameters that govern pointer or wheel acceleration.
+ */
+struct VelocityControlParameters {
+ // A scale factor that is multiplied with the raw velocity deltas
+ // prior to applying any other velocity control factors. The scale
+ // factor should be used to adapt the input device resolution
+ // (eg. counts per inch) to the output device resolution (eg. pixels per inch).
+ //
+ // Must be a positive value.
+ // Default is 1.0 (no scaling).
+ float scale;
+
+ // The scaled speed at which acceleration begins to be applied.
+ // This value establishes the upper bound of a low speed regime for
+ // small precise motions that are performed without any acceleration.
+ //
+ // Must be a non-negative value.
+ // Default is 0.0 (no low threshold).
+ float lowThreshold;
+
+ // The scaled speed at which maximum acceleration is applied.
+ // The difference between highThreshold and lowThreshold controls
+ // the range of speeds over which the acceleration factor is interpolated.
+ // The wider the range, the smoother the acceleration.
+ //
+ // Must be a non-negative value greater than or equal to lowThreshold.
+ // Default is 0.0 (no high threshold).
+ float highThreshold;
+
+ // The acceleration factor.
+ // When the speed is above the low speed threshold, the velocity will scaled
+ // by an interpolated value between 1.0 and this amount.
+ //
+ // Must be a positive greater than or equal to 1.0.
+ // Default is 1.0 (no acceleration).
+ float acceleration;
+
+ VelocityControlParameters() :
+ scale(1.0f), lowThreshold(0.0f), highThreshold(0.0f), acceleration(1.0f) {
+ }
+
+ VelocityControlParameters(float scale, float lowThreshold,
+ float highThreshold, float acceleration) :
+ scale(scale), lowThreshold(lowThreshold),
+ highThreshold(highThreshold), acceleration(acceleration) {
+ }
+};
+
+/*
+ * Implements mouse pointer and wheel speed control and acceleration.
+ */
+class VelocityControl {
+public:
+ VelocityControl();
+
+ /* Sets the various parameters. */
+ void setParameters(const VelocityControlParameters& parameters);
+
+ /* Resets the current movement counters to zero.
+ * This has the effect of nullifying any acceleration. */
+ void reset();
+
+ /* Translates a raw movement delta into an appropriately
+ * scaled / accelerated delta based on the current velocity. */
+ void move(nsecs_t eventTime, float* deltaX, float* deltaY);
+
+private:
+ // If no movements are received within this amount of time,
+ // we assume the movement has stopped and reset the movement counters.
+ static const nsecs_t STOP_TIME = 500 * 1000000; // 500 ms
+
+ VelocityControlParameters mParameters;
+
+ nsecs_t mLastMovementTime;
+ VelocityTracker::Position mRawPosition;
+ VelocityTracker mVelocityTracker;
+};
+
+
/*
* Describes the characteristics and capabilities of an input device.
*/
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 684c332..50b75d5 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -13,6 +13,10 @@
// Log debug messages about velocity tracking.
#define DEBUG_VELOCITY 0
+// Log debug messages about acceleration.
+#define DEBUG_ACCELERATION 0
+
+
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
@@ -20,6 +24,7 @@
#include <ui/Input.h>
#include <math.h>
+#include <limits.h>
#ifdef HAVE_ANDROID_OS
#include <binder/Parcel.h>
@@ -670,6 +675,11 @@
// --- VelocityTracker ---
+const uint32_t VelocityTracker::HISTORY_SIZE;
+const nsecs_t VelocityTracker::MAX_AGE;
+const nsecs_t VelocityTracker::MIN_WINDOW;
+const nsecs_t VelocityTracker::MIN_DURATION;
+
VelocityTracker::VelocityTracker() {
clear();
}
@@ -879,6 +889,85 @@
}
+// --- VelocityControl ---
+
+const nsecs_t VelocityControl::STOP_TIME;
+
+VelocityControl::VelocityControl() {
+ reset();
+}
+
+void VelocityControl::setParameters(const VelocityControlParameters& parameters) {
+ mParameters = parameters;
+ reset();
+}
+
+void VelocityControl::reset() {
+ mLastMovementTime = LLONG_MIN;
+ mRawPosition.x = 0;
+ mRawPosition.y = 0;
+ mVelocityTracker.clear();
+}
+
+void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) {
+ if ((deltaX && *deltaX) || (deltaY && *deltaY)) {
+ if (eventTime >= mLastMovementTime + STOP_TIME) {
+#if DEBUG_ACCELERATION
+ LOGD("VelocityControl: stopped, last movement was %0.3fms ago",
+ (eventTime - mLastMovementTime) * 0.000001f);
+#endif
+ reset();
+ }
+
+ mLastMovementTime = eventTime;
+ if (deltaX) {
+ mRawPosition.x += *deltaX;
+ }
+ if (deltaY) {
+ mRawPosition.y += *deltaY;
+ }
+ mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), &mRawPosition);
+
+ float vx, vy;
+ float scale = mParameters.scale;
+ if (mVelocityTracker.getVelocity(0, &vx, &vy)) {
+ float speed = hypotf(vx, vy) * scale;
+ if (speed >= mParameters.highThreshold) {
+ // Apply full acceleration above the high speed threshold.
+ scale *= mParameters.acceleration;
+ } else if (speed > mParameters.lowThreshold) {
+ // Linearly interpolate the acceleration to apply between the low and high
+ // speed thresholds.
+ scale *= 1 + (speed - mParameters.lowThreshold)
+ / (mParameters.highThreshold - mParameters.lowThreshold)
+ * (mParameters.acceleration - 1);
+ }
+
+#if DEBUG_ACCELERATION
+ LOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): "
+ "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f",
+ mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
+ mParameters.acceleration,
+ vx, vy, speed, scale / mParameters.scale);
+#endif
+ } else {
+#if DEBUG_ACCELERATION
+ LOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity",
+ mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
+ mParameters.acceleration);
+#endif
+ }
+
+ if (deltaX) {
+ *deltaX *= scale;
+ }
+ if (deltaY) {
+ *deltaY *= scale;
+ }
+ }
+}
+
+
// --- InputDeviceInfo ---
InputDeviceInfo::InputDeviceInfo() {
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index bf06f947..2e2768f 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -125,4 +125,7 @@
<!-- Default for Settings.Secure.LONG_PRESS_TIMEOUT_MILLIS -->
<integer name="def_long_press_timeout_millis">500</integer>
+ <!-- Default for Settings.System.POINTER_SPEED -->
+ <integer name="def_pointer_speed">0</integer>
+
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index d901c2c..2ed968b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1214,6 +1214,9 @@
loadBooleanSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME,
R.bool.def_notifications_use_ring_volume);
+ loadIntegerSetting(stmt, Settings.System.POINTER_SPEED,
+ R.integer.def_pointer_speed);
+
} finally {
if (stmt != null) stmt.close();
}
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index d80abe8..f748e7c 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -33,6 +33,7 @@
#include <hardware_legacy/power.h>
+#include <cutils/atomic.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/Timers.h>
@@ -127,6 +128,7 @@
mError(NO_INIT), mBuiltInKeyboardId(-1), mNextDeviceId(1),
mOpeningDevices(0), mClosingDevices(0),
mOpened(false), mNeedToSendFinishedDeviceScan(false),
+ mNeedToReopenDevices(0), mNeedToScanDevices(false),
mInputFdIndex(1) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
@@ -380,12 +382,10 @@
return NAME_NOT_FOUND;
}
-void EventHub::addExcludedDevice(const char* deviceName)
-{
+void EventHub::setExcludedDevices(const Vector<String8>& devices) {
AutoMutex _l(mLock);
- String8 name(deviceName);
- mExcludedDevices.push_back(name);
+ mExcludedDevices = devices;
}
bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
@@ -453,9 +453,11 @@
assert(bufferSize >= 1);
if (!mOpened) {
+ android_atomic_acquire_store(0, &mNeedToReopenDevices);
+
mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
mOpened = true;
- mNeedToSendFinishedDeviceScan = true;
+ mNeedToScanDevices = true;
}
struct input_event readBuffer[bufferSize];
@@ -465,6 +467,20 @@
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ // Reopen input devices if needed.
+ if (android_atomic_acquire_load(&mNeedToReopenDevices)) {
+ android_atomic_acquire_store(0, &mNeedToReopenDevices);
+
+ LOGI("Reopening all input devices due to a configuration change.");
+
+ AutoMutex _l(mLock);
+ while (mDevices.size() > 1) {
+ closeDeviceAtIndexLocked(mDevices.size() - 1);
+ }
+ mNeedToScanDevices = true;
+ break; // return to the caller before we actually rescan
+ }
+
// Report any devices that had last been added/removed.
while (mClosingDevices) {
Device* device = mClosingDevices;
@@ -482,6 +498,12 @@
}
}
+ if (mNeedToScanDevices) {
+ mNeedToScanDevices = false;
+ scanDevices();
+ mNeedToSendFinishedDeviceScan = true;
+ }
+
while (mOpeningDevices != NULL) {
Device* device = mOpeningDevices;
LOGV("Reporting device opened: id=%d, name=%s\n",
@@ -683,13 +705,14 @@
pollfd.revents = 0;
mFds.push(pollfd);
mDevices.push(NULL);
+ return true;
+}
- res = scanDir(DEVICE_PATH);
+void EventHub::scanDevices() {
+ int res = scanDir(DEVICE_PATH);
if(res < 0) {
LOGE("scan dir failed for %s\n", DEVICE_PATH);
}
-
- return true;
}
// ----------------------------------------------------------------------------
@@ -742,12 +765,10 @@
}
// Check to see if the device is on our excluded list
- List<String8>::iterator iter = mExcludedDevices.begin();
- List<String8>::iterator end = mExcludedDevices.end();
- for ( ; iter != end; iter++) {
- const char* test = *iter;
- if (identifier.name == test) {
- LOGI("ignoring event id %s driver %s\n", devicePath, test);
+ for (size_t i = 0; i < mExcludedDevices.size(); i++) {
+ const String8& item = mExcludedDevices.itemAt(i);
+ if (identifier.name == item) {
+ LOGI("ignoring event id %s driver %s\n", devicePath, item.string());
close(fd);
return -1;
}
@@ -1210,6 +1231,10 @@
return 0;
}
+void EventHub::reopenDevices() {
+ android_atomic_release_store(1, &mNeedToReopenDevices);
+}
+
void EventHub::dump(String8& dump) {
dump.append("Event Hub State:\n");
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 4d26a95..853a0bd 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -178,9 +178,9 @@
virtual status_t mapAxis(int32_t deviceId, int scancode,
AxisInfo* outAxisInfo) const = 0;
- // exclude a particular device from opening
- // this can be used to ignore input devices for sensors
- virtual void addExcludedDevice(const char* deviceName) = 0;
+ // Sets devices that are excluded from opening.
+ // This can be used to ignore input devices for sensors.
+ virtual void setExcludedDevices(const Vector<String8>& devices) = 0;
/*
* Wait for events to become available and returns them.
@@ -215,6 +215,8 @@
virtual void getVirtualKeyDefinitions(int32_t deviceId,
Vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
+ virtual void reopenDevices() = 0;
+
virtual void dump(String8& dump) = 0;
};
@@ -242,7 +244,7 @@
virtual status_t mapAxis(int32_t deviceId, int scancode,
AxisInfo* outAxisInfo) const;
- virtual void addExcludedDevice(const char* deviceName);
+ virtual void setExcludedDevices(const Vector<String8>& devices);
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const;
@@ -259,6 +261,8 @@
virtual void getVirtualKeyDefinitions(int32_t deviceId,
Vector<VirtualKeyDefinition>& outVirtualKeys) const;
+ virtual void reopenDevices();
+
virtual void dump(String8& dump);
protected:
@@ -271,6 +275,7 @@
int closeDevice(const char *devicePath);
int closeDeviceAtIndexLocked(int index);
int scanDir(const char *dirname);
+ void scanDevices();
int readNotify(int nfd);
status_t mError;
@@ -333,7 +338,9 @@
bool mOpened;
bool mNeedToSendFinishedDeviceScan;
- List<String8> mExcludedDevices;
+ volatile int32_t mNeedToReopenDevices; // must be modified atomically
+ bool mNeedToScanDevices;
+ Vector<String8> mExcludedDevices;
// device ids that report particular switches.
int32_t mSwitches[SW_MAX + 1];
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index f2b34dd..a22ec1c 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -38,6 +38,7 @@
#include "InputReader.h"
+#include <cutils/atomic.h>
#include <cutils/log.h>
#include <ui/Keyboard.h>
#include <ui/VirtualKeyMap.h>
@@ -219,10 +220,9 @@
const sp<InputReaderPolicyInterface>& policy,
const sp<InputDispatcherInterface>& dispatcher) :
mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
- mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX) {
- mPolicy->getReaderConfiguration(&mConfig);
-
- configureExcludedDevices();
+ mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
+ mRefreshConfiguration(0) {
+ configure(true /*firstTime*/);
updateGlobalMetaState();
updateInputConfiguration();
}
@@ -234,6 +234,11 @@
}
void InputReader::loopOnce() {
+ if (android_atomic_acquire_load(&mRefreshConfiguration)) {
+ android_atomic_release_store(0, &mRefreshConfiguration);
+ configure(false /*firstTime*/);
+ }
+
int32_t timeoutMillis = -1;
if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -454,9 +459,12 @@
mDispatcher->notifyConfigurationChanged(when);
}
-void InputReader::configureExcludedDevices() {
- for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
- mEventHub->addExcludedDevice(mConfig.excludedDeviceNames[i]);
+void InputReader::configure(bool firstTime) {
+ mPolicy->getReaderConfiguration(&mConfig);
+ mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
+
+ if (!firstTime) {
+ mEventHub->reopenDevices();
}
}
@@ -677,6 +685,10 @@
} // release device registy reader lock
}
+void InputReader::refreshConfiguration() {
+ android_atomic_release_store(1, &mRefreshConfiguration);
+}
+
void InputReader::dump(String8& dump) {
mEventHub->dump(dump);
dump.append("\n");
@@ -707,6 +719,20 @@
dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
mConfig.virtualKeyQuietTime * 0.000001f);
+ dump.appendFormat(INDENT2 "PointerVelocityControlParameters: "
+ "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
+ mConfig.pointerVelocityControlParameters.scale,
+ mConfig.pointerVelocityControlParameters.lowThreshold,
+ mConfig.pointerVelocityControlParameters.highThreshold,
+ mConfig.pointerVelocityControlParameters.acceleration);
+
+ dump.appendFormat(INDENT2 "WheelVelocityControlParameters: "
+ "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
+ mConfig.wheelVelocityControlParameters.scale,
+ mConfig.wheelVelocityControlParameters.lowThreshold,
+ mConfig.wheelVelocityControlParameters.highThreshold,
+ mConfig.wheelVelocityControlParameters.acceleration);
+
dump.appendFormat(INDENT2 "PointerGesture:\n");
dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n",
mConfig.pointerGestureQuietInterval * 0.000001f);
@@ -1371,6 +1397,10 @@
mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
+
+ mPointerVelocityControl.setParameters(getConfig()->pointerVelocityControlParameters);
+ mWheelXVelocityControl.setParameters(getConfig()->wheelVelocityControlParameters);
+ mWheelYVelocityControl.setParameters(getConfig()->wheelVelocityControlParameters);
}
void CursorInputMapper::configureParameters() {
@@ -1432,6 +1462,11 @@
}
} // release lock
+ // Reset velocity.
+ mPointerVelocityControl.reset();
+ mWheelXVelocityControl.reset();
+ mWheelYVelocityControl.reset();
+
// Synthesize button up event on reset.
nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
mAccumulator.clear();
@@ -1585,11 +1620,16 @@
} else {
vscroll = 0;
}
+ mWheelYVelocityControl.move(when, NULL, &vscroll);
+
if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
hscroll = mAccumulator.relHWheel;
} else {
hscroll = 0;
}
+ mWheelXVelocityControl.move(when, &hscroll, NULL);
+
+ mPointerVelocityControl.move(when, &deltaX, &deltaY);
if (mPointerController != NULL) {
if (deltaX != 0 || deltaY != 0 || vscroll != 0 || hscroll != 0
@@ -1806,6 +1846,7 @@
mLocked.orientedRanges.haveOrientation = false;
mPointerGesture.reset();
+ mPointerGesture.pointerVelocityControl.setParameters(mConfig->pointerVelocityControlParameters);
}
void TouchInputMapper::configure() {
@@ -2239,11 +2280,10 @@
mLocked.associatedDisplayHeight);
// Scale movements such that one whole swipe of the touch pad covers a
- // given area relative to the diagonal size of the display.
+ // given area relative to the diagonal size of the display when no acceleration
+ // is applied.
// Assume that the touch pad has a square aspect ratio such that movements in
// X and Y of the same number of raw units cover the same physical distance.
- const float scaleFactor = 0.8f;
-
mLocked.pointerGestureXMovementScale = mConfig->pointerGestureMovementSpeedRatio
* displayDiagonal / rawDiagonal;
mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale;
@@ -3247,6 +3287,9 @@
if (!sendEvents) {
return;
}
+ if (finishPreviousGesture) {
+ cancelPreviousGesture = false;
+ }
// Switch pointer presentation.
mPointerController->setPresentation(
@@ -3436,6 +3479,8 @@
mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
mPointerGesture.currentGestureIdBits.clear();
+ mPointerGesture.pointerVelocityControl.reset();
+
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
mPointerGesture.spotIdBits.clear();
@@ -3530,6 +3575,8 @@
mPointerGesture.currentGestureMode = PointerGesture::QUIET;
mPointerGesture.currentGestureIdBits.clear();
+ mPointerGesture.pointerVelocityControl.reset();
+
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
mPointerGesture.spotIdBits.clear();
@@ -3561,46 +3608,48 @@
// Switch pointers if needed.
// Find the fastest pointer and follow it.
- if (activeTouchId >= 0) {
- if (mCurrentTouch.pointerCount > 1) {
- int32_t bestId = -1;
- float bestSpeed = mConfig->pointerGestureDragMinSwitchSpeed;
- for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
- uint32_t id = mCurrentTouch.pointers[i].id;
- float vx, vy;
- if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
- float speed = hypotf(vx, vy);
- if (speed > bestSpeed) {
- bestId = id;
- bestSpeed = speed;
- }
+ if (activeTouchId >= 0 && mCurrentTouch.pointerCount > 1) {
+ int32_t bestId = -1;
+ float bestSpeed = mConfig->pointerGestureDragMinSwitchSpeed;
+ for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
+ uint32_t id = mCurrentTouch.pointers[i].id;
+ float vx, vy;
+ if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
+ float speed = hypotf(vx, vy);
+ if (speed > bestSpeed) {
+ bestId = id;
+ bestSpeed = speed;
}
}
- if (bestId >= 0 && bestId != activeTouchId) {
- mPointerGesture.activeTouchId = activeTouchId = bestId;
- activeTouchChanged = true;
+ }
+ if (bestId >= 0 && bestId != activeTouchId) {
+ mPointerGesture.activeTouchId = activeTouchId = bestId;
+ activeTouchChanged = true;
#if DEBUG_GESTURES
- LOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
- "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
+ LOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
+ "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
#endif
- }
}
+ }
- if (mLastTouch.idBits.hasBit(activeTouchId)) {
- const PointerData& currentPointer =
- mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]];
- const PointerData& lastPointer =
- mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]];
- float deltaX = (currentPointer.x - lastPointer.x)
- * mLocked.pointerGestureXMovementScale;
- float deltaY = (currentPointer.y - lastPointer.y)
- * mLocked.pointerGestureYMovementScale;
+ if (activeTouchId >= 0 && mLastTouch.idBits.hasBit(activeTouchId)) {
+ const PointerData& currentPointer =
+ mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]];
+ const PointerData& lastPointer =
+ mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]];
+ float deltaX = (currentPointer.x - lastPointer.x)
+ * mLocked.pointerGestureXMovementScale;
+ float deltaY = (currentPointer.y - lastPointer.y)
+ * mLocked.pointerGestureYMovementScale;
- // Move the pointer using a relative motion.
- // When using spots, the click will occur at the position of the anchor
- // spot and all other spots will move there.
- mPointerController->move(deltaX, deltaY);
- }
+ mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY);
+
+ // Move the pointer using a relative motion.
+ // When using spots, the click will occur at the position of the anchor
+ // spot and all other spots will move there.
+ mPointerController->move(deltaX, deltaY);
+ } else {
+ mPointerGesture.pointerVelocityControl.reset();
}
float x, y;
@@ -3700,6 +3749,8 @@
}
}
+ mPointerGesture.pointerVelocityControl.reset();
+
if (!tapped) {
#if DEBUG_GESTURES
LOGD("Gestures: NEUTRAL");
@@ -3756,9 +3807,13 @@
float deltaY = (currentPointer.y - lastPointer.y)
* mLocked.pointerGestureYMovementScale;
+ mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY);
+
// Move the pointer using a relative motion.
// When using spots, the hover or drag will occur at the position of the anchor spot.
mPointerController->move(deltaX, deltaY);
+ } else {
+ mPointerGesture.pointerVelocityControl.reset();
}
bool down;
@@ -3820,16 +3875,32 @@
// a decision to transition into SWIPE or FREEFORM mode accordingly.
LOG_ASSERT(activeTouchId >= 0);
- bool needReference = false;
bool settled = when >= mPointerGesture.firstTouchTime
+ mConfig->pointerGestureMultitouchSettleInterval;
if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
&& mPointerGesture.lastGestureMode != PointerGesture::SWIPE
&& mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
*outFinishPreviousGesture = true;
+ } else if (!settled && mCurrentTouch.pointerCount > mLastTouch.pointerCount) {
+ // Additional pointers have gone down but not yet settled.
+ // Reset the gesture.
+#if DEBUG_GESTURES
+ LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
+ "settle time remaining %0.3fms",
+ (mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when)
+ * 0.000001f);
+#endif
+ *outCancelPreviousGesture = true;
+ } else {
+ // Continue previous gesture.
+ mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
+ }
+
+ if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
mPointerGesture.currentGestureMode = PointerGesture::PRESS;
mPointerGesture.activeGestureId = 0;
mPointerGesture.referenceIdBits.clear();
+ mPointerGesture.pointerVelocityControl.reset();
if (settled && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
&& mLastTouch.idBits.hasBit(mPointerGesture.activeTouchId)) {
@@ -3850,37 +3921,18 @@
mPointerGesture.referenceGestureX = c.getAxisValue(AMOTION_EVENT_AXIS_X);
mPointerGesture.referenceGestureY = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
} else {
+ // Use the centroid and pointer location as the reference points for the gesture.
#if DEBUG_GESTURES
LOGD("Gestures: Using centroid as reference for MULTITOUCH, "
"settle time remaining %0.3fms",
(mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when)
* 0.000001f);
#endif
- needReference = true;
+ mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX,
+ &mPointerGesture.referenceTouchY);
+ mPointerController->getPosition(&mPointerGesture.referenceGestureX,
+ &mPointerGesture.referenceGestureY);
}
- } else if (!settled && mCurrentTouch.pointerCount > mLastTouch.pointerCount) {
- // Additional pointers have gone down but not yet settled.
- // Reset the gesture.
-#if DEBUG_GESTURES
- LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
- "settle time remaining %0.3fms",
- (mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when)
- * 0.000001f);
-#endif
- *outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::PRESS;
- mPointerGesture.activeGestureId = 0;
- } else {
- // Continue previous gesture.
- mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
- }
-
- if (needReference) {
- // Use the centroid and pointer location as the reference points for the gesture.
- mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX,
- &mPointerGesture.referenceTouchY);
- mPointerController->getPosition(&mPointerGesture.referenceGestureX,
- &mPointerGesture.referenceGestureY);
}
if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
@@ -4010,10 +4062,14 @@
mPointerGesture.referenceTouchX += commonDeltaX;
mPointerGesture.referenceTouchY += commonDeltaY;
- mPointerGesture.referenceGestureX +=
- commonDeltaX * mLocked.pointerGestureXMovementScale;
- mPointerGesture.referenceGestureY +=
- commonDeltaY * mLocked.pointerGestureYMovementScale;
+
+ commonDeltaX *= mLocked.pointerGestureXMovementScale;
+ commonDeltaY *= mLocked.pointerGestureYMovementScale;
+ mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
+
+ mPointerGesture.referenceGestureX += commonDeltaX;
+ mPointerGesture.referenceGestureY += commonDeltaY;
+
clampPositionUsingPointerBounds(mPointerController,
&mPointerGesture.referenceGestureX,
&mPointerGesture.referenceGestureY);
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index db4679b..5028b60 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -62,6 +62,12 @@
// Devices with these names will be ignored.
Vector<String8> excludedDeviceNames;
+ // Velocity control parameters for mouse pointer movements.
+ VelocityControlParameters pointerVelocityControlParameters;
+
+ // Velocity control parameters for mouse wheel movements.
+ VelocityControlParameters wheelVelocityControlParameters;
+
// Quiet time between certain pointer gesture transitions.
// Time to allow for all fingers or buttons to settle into a stable state before
// starting a new gesture.
@@ -128,6 +134,8 @@
filterTouchEvents(false),
filterJumpyTouchEvents(false),
virtualKeyQuietTime(0),
+ pointerVelocityControlParameters(1.0f, 80.0f, 400.0f, 4.0f),
+ wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f),
pointerGestureQuietInterval(100 * 1000000LL), // 100 ms
pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second
pointerGestureTapInterval(150 * 1000000LL), // 150 ms
@@ -137,7 +145,7 @@
pointerGestureMultitouchMinSpeed(150.0f), // 150 pixels per second
pointerGestureSwipeTransitionAngleCosine(0.5f), // cosine of 45degrees
pointerGestureSwipeMaxWidthRatio(0.333f),
- pointerGestureMovementSpeedRatio(0.8f),
+ pointerGestureMovementSpeedRatio(0.3f),
pointerGestureZoomSpeedRatio(0.3f) { }
};
@@ -226,6 +234,9 @@
/* Determine whether physical keys exist for the given framework-domain key codes. */
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
+
+ /* Reopens and reconfigures all input devices. */
+ virtual void refreshConfiguration() = 0;
};
@@ -290,6 +301,8 @@
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
+ virtual void refreshConfiguration();
+
protected:
// These methods are protected virtual so they can be overridden and instrumented
// by test cases.
@@ -331,18 +344,17 @@
void timeoutExpired(nsecs_t when);
void handleConfigurationChanged(nsecs_t when);
- void configureExcludedDevices();
// state management for all devices
Mutex mStateLock;
- int32_t mGlobalMetaState;
+ int32_t mGlobalMetaState; // guarded by mStateLock
virtual void updateGlobalMetaState();
virtual int32_t getGlobalMetaState();
virtual void fadePointer();
- InputConfiguration mInputConfiguration;
+ InputConfiguration mInputConfiguration; // guarded by mStateLock
void updateInputConfiguration();
nsecs_t mDisableVirtualKeysTimeout; // only accessed by reader thread
@@ -350,9 +362,12 @@
virtual bool shouldDropVirtualKey(nsecs_t now,
InputDevice* device, int32_t keyCode, int32_t scanCode);
- nsecs_t mNextTimeout; // only accessed by reader thread
+ nsecs_t mNextTimeout; // only accessed by reader thread, not guarded
virtual void requestTimeoutAtTime(nsecs_t when);
+ volatile int32_t mRefreshConfiguration; // atomic
+ void configure(bool firstTime);
+
// state queries
typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
int32_t getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
@@ -629,6 +644,12 @@
float mVWheelScale;
float mHWheelScale;
+ // Velocity controls for mouse pointer and wheel movements.
+ // The controls for X and Y wheel movements are separate to keep them decoupled.
+ VelocityControl mPointerVelocityControl;
+ VelocityControl mWheelXVelocityControl;
+ VelocityControl mWheelYVelocityControl;
+
sp<PointerControllerInterface> mPointerController;
struct LockedState {
@@ -1133,6 +1154,9 @@
// A velocity tracker for determining whether to switch active pointers during drags.
VelocityTracker velocityTracker;
+ // Velocity control for pointer movements.
+ VelocityControl pointerVelocityControl;
+
void reset() {
firstTouchTime = LLONG_MIN;
activeTouchId = -1;
@@ -1147,6 +1171,7 @@
velocityTracker.clear();
resetTap();
resetQuietTime();
+ pointerVelocityControl.reset();
}
void resetTap() {
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index b5f603a..e85ae1f 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -617,8 +617,8 @@
return NAME_NOT_FOUND;
}
- virtual void addExcludedDevice(const char* deviceName) {
- mExcludedDevices.add(String8(deviceName));
+ virtual void setExcludedDevices(const Vector<String8>& devices) {
+ mExcludedDevices = devices;
}
virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
@@ -716,6 +716,9 @@
virtual void dump(String8& dump) {
}
+
+ virtual void reopenDevices() {
+ }
};
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index ab781f4..4eda684 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -23,10 +23,14 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.database.ContentObserver;
import android.os.Environment;
+import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
import android.os.SystemProperties;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
import android.util.Xml;
import android.view.InputChannel;
@@ -56,7 +60,7 @@
private final Callbacks mCallbacks;
private final Context mContext;
private final WindowManagerService mWindowManagerService;
-
+
private static native void nativeInit(Context context,
Callbacks callbacks, MessageQueue messageQueue);
private static native void nativeStart();
@@ -85,6 +89,7 @@
private static native int[] nativeGetInputDeviceIds();
private static native boolean nativeTransferTouchFocus(InputChannel fromChannel,
InputChannel toChannel);
+ private static native void nativeSetPointerSpeed(int speed);
private static native String nativeDump();
// Input event injection constants defined in InputDispatcher.h.
@@ -123,10 +128,13 @@
Slog.i(TAG, "Initializing input manager");
nativeInit(mContext, mCallbacks, looper.getQueue());
}
-
+
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart();
+
+ registerPointerSpeedSettingObserver();
+ updatePointerSpeedFromSettings();
}
public void setDisplaySize(int displayId, int width, int height) {
@@ -359,6 +367,42 @@
return nativeTransferTouchFocus(fromChannel, toChannel);
}
+ /**
+ * Set the pointer speed.
+ * @param speed The pointer speed as a value between -7 (slowest) and 7 (fastest)
+ * where 0 is the default speed.
+ */
+ public void setPointerSpeed(int speed) {
+ speed = Math.min(Math.max(speed, -7), 7);
+ nativeSetPointerSpeed(speed);
+ }
+
+ public void updatePointerSpeedFromSettings() {
+ int speed = getPointerSpeedSetting(0);
+ setPointerSpeed(speed);
+ }
+
+ private void registerPointerSpeedSettingObserver() {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
+ new ContentObserver(mWindowManagerService.mH) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updatePointerSpeedFromSettings();
+ }
+ });
+ }
+
+ private int getPointerSpeedSetting(int defaultValue) {
+ int speed = defaultValue;
+ try {
+ speed = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.POINTER_SPEED);
+ } catch (SettingNotFoundException snfe) {
+ }
+ return speed;
+ }
+
public void dump(PrintWriter pw) {
String dumpStr = nativeDump();
if (dumpStr != null) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 7760897..4ff6b06 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -5947,6 +5947,19 @@
}
}
+ /**
+ * Temporarily set the pointer speed. Does not save the new setting.
+ * Used by the settings application.
+ */
+ public void setPointerSpeed(int speed) {
+ if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
+ "setPointerSpeed()")) {
+ throw new SecurityException("Requires SET_POINTER_SPEED permission");
+ }
+
+ mInputManager.setPointerSpeed(speed);
+ }
+
private WindowState getFocusedWindow() {
synchronized (mWindowMap) {
return getFocusedWindowLocked();
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index fef41c9..2704647 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -53,6 +53,11 @@
namespace android {
+// The exponent used to calculate the pointer speed scaling factor.
+// The scaling factor is calculated as 2 ^ (speed * exponent),
+// where the speed ranges from -7 to + 7 and is supplied by the user.
+static const float POINTER_SPEED_EXPONENT = 1.0f / 3;
+
static struct {
jclass clazz;
@@ -179,6 +184,7 @@
void setFocusedApplication(JNIEnv* env, jobject applicationObj);
void setInputDispatchMode(bool enabled, bool frozen);
void setSystemUiVisibility(int32_t visibility);
+ void setPointerSpeed(int32_t speed);
/* --- InputReaderPolicyInterface implementation --- */
@@ -227,6 +233,9 @@
// System UI visibility.
int32_t systemUiVisibility;
+ // Pointer speed.
+ int32_t pointerSpeed;
+
// Sprite controller singleton, created on first use.
sp<SpriteController> spriteController;
@@ -266,6 +275,7 @@
mLocked.displayOrientation = ROTATION_0;
mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
+ mLocked.pointerSpeed = 0;
}
sp<EventHub> eventHub = new EventHub();
@@ -429,6 +439,13 @@
if (!checkAndClearExceptionFromCallback(env, "getTouchSlop")) {
outConfig->pointerGestureTapSlop = touchSlop;
}
+
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ outConfig->pointerVelocityControlParameters.scale = exp2f(mLocked.pointerSpeed
+ * POINTER_SPEED_EXPONENT);
+ } // release lock
}
sp<PointerControllerInterface> NativeInputManager::obtainPointerController(int32_t deviceId) {
@@ -634,6 +651,17 @@
: PointerController::INACTIVITY_TIMEOUT_NORMAL);
}
+void NativeInputManager::setPointerSpeed(int32_t speed) {
+ AutoMutex _l(mLock);
+
+ if (mLocked.pointerSpeed != speed) {
+ LOGI("Setting pointer speed to %d.", speed);
+ mLocked.pointerSpeed = speed;
+
+ mInputManager->getReader()->refreshConfiguration();
+ }
+}
+
bool NativeInputManager::isScreenOn() {
return android_server_PowerManagerService_isScreenOn();
}
@@ -1180,6 +1208,15 @@
transferTouchFocus(fromChannel, toChannel);
}
+static void android_server_InputManager_nativeSetPointerSpeed(JNIEnv* env,
+ jclass clazz, jint speed) {
+ if (checkInputManagerUnitialized(env)) {
+ return;
+ }
+
+ gNativeInputManager->setPointerSpeed(speed);
+}
+
static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
if (checkInputManagerUnitialized(env)) {
return NULL;
@@ -1234,6 +1271,8 @@
(void*) android_server_InputManager_nativeGetInputConfiguration },
{ "nativeTransferTouchFocus", "(Landroid/view/InputChannel;Landroid/view/InputChannel;)Z",
(void*) android_server_InputManager_nativeTransferTouchFocus },
+ { "nativeSetPointerSpeed", "(I)V",
+ (void*) android_server_InputManager_nativeSetPointerSpeed },
{ "nativeDump", "()Ljava/lang/String;",
(void*) android_server_InputManager_nativeDump },
};
diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java
index b40f945..cafc79b 100644
--- a/telephony/java/com/android/internal/telephony/IccConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccConstants.java
@@ -58,6 +58,12 @@
static final int EF_CST = 0x6f32;
static final int EF_RUIM_SPN =0x6F41;
+ // ETSI TS.102.221
+ static final int EF_PL = 0x2F05;
+ // 3GPP2 C.S0065
+ static final int EF_CSIM_LI = 0x6F3A;
+ static final int EF_CSIM_SPN =0x6F41;
+
//ISIM access
static final int EF_IMPU = 0x6f04;
static final int EF_IMPI = 0x6f02;
diff --git a/telephony/java/com/android/internal/telephony/IccFileHandler.java b/telephony/java/com/android/internal/telephony/IccFileHandler.java
index 92ddd2c..93b9b79 100644
--- a/telephony/java/com/android/internal/telephony/IccFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/IccFileHandler.java
@@ -529,6 +529,7 @@
return MF_SIM + DF_TELECOM;
case EF_ICCID:
+ case EF_PL:
return MF_SIM;
case EF_IMG:
return MF_SIM + DF_TELECOM + DF_GRAPHICS;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
index 5733164..fe2fcb2 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -58,8 +58,9 @@
@Override
protected void initSstIcc() {
mSST = new CdmaLteServiceStateTracker(this);
- mIccRecords = new SIMRecords(this);
+ mIccRecords = new CdmaLteUiccRecords(this);
mIccCard = new SimCard(this, LOG_TAG, DBG);
+ mIccFileHandler = new CdmaLteUiccFileHandler(this);
}
@Override
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index c85f7d8..a283062 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -156,13 +156,13 @@
mSST = new CdmaServiceStateTracker(this);
mIccRecords = new RuimRecords(this);
mIccCard = new RuimCard(this, LOG_TAG, DBG);
+ mIccFileHandler = new RuimFileHandler(this);
}
protected void init(Context context, PhoneNotifier notifier) {
mCM.setPhoneType(Phone.PHONE_TYPE_CDMA);
mCT = new CdmaCallTracker(this);
mSMS = new CdmaSMSDispatcher(this);
- mIccFileHandler = new RuimFileHandler(this);
mDataConnectionTracker = new CdmaDataConnectionTracker (this);
mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this, mSMS);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java
new file mode 100644
index 0000000..2aede29
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.util.Log;
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccFileHandler;
+
+/**
+ * {@hide}
+ */
+public final class CdmaLteUiccFileHandler extends IccFileHandler {
+ static final String LOG_TAG = "CDMA";
+
+ CdmaLteUiccFileHandler(CDMALTEPhone phone) {
+ super(phone);
+ }
+
+ protected String getEFPath(int efid) {
+ switch(efid) {
+ case EF_CSIM_SPN:
+ case EF_CSIM_LI:
+ return MF_SIM + DF_CDMA;
+ case EF_AD:
+ return MF_SIM + DF_GSM;
+ }
+ return getCommonIccEFPath(efid);
+ }
+
+ protected void logd(String msg) {
+ Log.d(LOG_TAG, "[CdmaLteUiccFileHandler] " + msg);
+ }
+
+ protected void loge(String msg) {
+ Log.e(LOG_TAG, "[CdmaLteUiccFileHandler] " + msg);
+ }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
new file mode 100755
index 0000000..78879d6
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.telephony.cdma;
+
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.telephony.gsm.SIMRecords;
+import android.os.AsyncResult;
+import android.os.Message;
+import android.os.SystemProperties;
+import android.util.Log;
+
+
+/**
+ * {@hide}
+ */
+public final class CdmaLteUiccRecords extends SIMRecords {
+ // From CSIM application
+ private byte[] mEFpl = null;
+ private byte[] mEFli = null;
+ boolean csimSpnDisplayCondition = false;
+
+ private static final int EVENT_GET_PL_DONE = CSIM_EVENT_BASE;
+ private static final int EVENT_GET_CSIM_LI_DONE = CSIM_EVENT_BASE + 1;
+ private static final int EVENT_GET_CSIM_SPN_DONE = CSIM_EVENT_BASE + 2;
+
+ public CdmaLteUiccRecords(PhoneBase p) {
+ super(p);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ AsyncResult ar;
+ byte data[];
+
+ boolean isCsimRecordLoadResponse = false;
+
+ try { switch (msg.what) {
+ case EVENT_GET_PL_DONE:
+ // Refer to ETSI TS.102.221
+ if (DBG) log("EF_GET_EF_PL_DONE");
+ isCsimRecordLoadResponse = true;
+
+ ar = (AsyncResult) msg.obj;
+
+ if (ar.exception != null) {
+ Log.e(LOG_TAG, "ar.exception = " + ar.exception);
+ break;
+ }
+
+ mEFpl = (byte[]) ar.result;
+ if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEFpl));
+ break;
+
+ case EVENT_GET_CSIM_LI_DONE:
+ // Refer to C.S0065 5.2.26
+ if (DBG) log("EVENT_GET_CSIM_LI_DONE");
+ isCsimRecordLoadResponse = true;
+
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception != null) {
+ Log.e(LOG_TAG, "ar.exception = " + ar.exception);
+ break;
+ }
+
+ mEFli = (byte[]) ar.result;
+ // convert csim efli data to iso 639 format
+ for (int i = 0; i < mEFli.length; i+=2) {
+ switch(mEFli[i+1]) {
+ case 0x01: mEFli[i] = 'e'; mEFli[i+1] = 'n';break;
+ case 0x02: mEFli[i] = 'f'; mEFli[i+1] = 'r';break;
+ case 0x03: mEFli[i] = 'e'; mEFli[i+1] = 's';break;
+ case 0x04: mEFli[i] = 'j'; mEFli[i+1] = 'a';break;
+ case 0x05: mEFli[i] = 'k'; mEFli[i+1] = 'o';break;
+ case 0x06: mEFli[i] = 'z'; mEFli[i+1] = 'h';break;
+ case 0x07: mEFli[i] = 'h'; mEFli[i+1] = 'e';break;
+ default: mEFli[i] = ' '; mEFli[i+1] = ' ';
+ }
+ }
+
+ if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEFli));
+ break;
+ case EVENT_GET_CSIM_SPN_DONE:
+ // Refer to C.S0065 5.2.32
+ if (DBG) log("EVENT_GET_CSIM_SPN_DONE");
+ isCsimRecordLoadResponse = true;
+ ar = (AsyncResult) msg.obj;
+
+ if (ar.exception != null) {
+ Log.e(LOG_TAG, "ar.exception=" + ar.exception);
+ break;
+ }
+ onGetCSimSpnDone(ar);
+ break;
+ default:
+ super.handleMessage(msg);
+ }}catch (RuntimeException exc) {
+ Log.w(LOG_TAG, "Exception parsing SIM record", exc);
+ } finally {
+ if (isCsimRecordLoadResponse) {
+ onRecordLoaded();
+ }
+ }
+ }
+
+ @Override
+ protected void onRecordLoaded() {
+ // One record loaded successfully or failed, In either case
+ // we need to update the recordsToLoad count
+ recordsToLoad -= 1;
+
+ if (recordsToLoad == 0 && recordsRequested == true) {
+ onAllRecordsLoaded();
+ } else if (recordsToLoad < 0) {
+ Log.e(LOG_TAG, "SIMRecords: recordsToLoad <0, programmer error suspected");
+ recordsToLoad = 0;
+ }
+ }
+
+ @Override
+ protected void fetchSimRecords() {
+ IccFileHandler iccFh = phone.getIccFileHandler();
+ recordsRequested = true;
+
+ phone.mCM.getIMSI(obtainMessage(EVENT_GET_IMSI_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFTransparent(EF_PL, obtainMessage(EVENT_GET_PL_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFTransparent(EF_CSIM_LI, obtainMessage(EVENT_GET_CSIM_LI_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFTransparent(EF_CSIM_SPN, obtainMessage(EVENT_GET_CSIM_SPN_DONE));
+ recordsToLoad++;
+ }
+
+ private void onGetCSimSpnDone(AsyncResult ar) {
+ byte[] data = (byte[]) ar.result;
+ if (DBG) log("CSIM_SPN=" +
+ IccUtils.bytesToHexString(data));
+
+ // C.S0065 for EF_SPN decoding
+ csimSpnDisplayCondition = ((0x02 & data[0]) > 0)?true:false;
+
+ int encoding = data[1];
+ int language = data[2];
+ byte[] spnData = new byte[32];
+ System.arraycopy(data, 3, spnData, 0, (data.length < 32)?data.length:32);
+
+ int numBytes;
+ for (numBytes = 0; numBytes < spnData.length; numBytes++) {
+ if ((spnData[numBytes] & 0xFF) == 0xFF) break;
+ }
+
+ if (numBytes == 0) {
+ spn = "";
+ return;
+ }
+ try {
+ switch (encoding) {
+ case UserData.ENCODING_OCTET:
+ case UserData.ENCODING_LATIN:
+ spn = new String(spnData, 0, numBytes, "ISO-8859-1");
+ break;
+ case UserData.ENCODING_IA5:
+ case UserData.ENCODING_GSM_7BIT_ALPHABET:
+ case UserData.ENCODING_7BIT_ASCII:
+ spn = GsmAlphabet.gsm7BitPackedToString(spnData, 0, (numBytes*8)/7);
+ break;
+ case UserData.ENCODING_UNICODE_16:
+ spn = new String(spnData, 0, numBytes, "utf-16");
+ break;
+ default:
+ log("SPN encoding not supported");
+ }
+ } catch(Exception e) {
+ log("spn decode error: " + e);
+ }
+ if (DBG) log("spn=" + spn);
+ if (DBG) log("spnCondition=" + csimSpnDisplayCondition);
+ phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, spn);
+ }
+
+ public byte[] getPreferredLanguage() {
+ return mEFpl;
+ }
+
+ public byte[] getLanguageIndication() {
+ return mEFli;
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index 4cd9440..b0bad56 100755
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -45,12 +45,12 @@
/**
* {@hide}
*/
-public final class SIMRecords extends IccRecords {
- static final String LOG_TAG = "GSM";
+public class SIMRecords extends IccRecords {
+ protected static final String LOG_TAG = "GSM";
private static final boolean CRASH_RIL = false;
- private static final boolean DBG = true;
+ protected static final boolean DBG = true;
// ***** Instance Variables
@@ -120,13 +120,13 @@
private static final int EVENT_SIM_READY = 1;
private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 2;
- private static final int EVENT_GET_IMSI_DONE = 3;
- private static final int EVENT_GET_ICCID_DONE = 4;
+ protected static final int EVENT_GET_IMSI_DONE = 3;
+ protected static final int EVENT_GET_ICCID_DONE = 4;
private static final int EVENT_GET_MBI_DONE = 5;
private static final int EVENT_GET_MBDN_DONE = 6;
private static final int EVENT_GET_MWIS_DONE = 7;
private static final int EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE = 8;
- private static final int EVENT_GET_AD_DONE = 9; // Admin data on SIM
+ protected static final int EVENT_GET_AD_DONE = 9; // Admin data on SIM
private static final int EVENT_GET_MSISDN_DONE = 10;
private static final int EVENT_GET_CPHS_MAILBOX_DONE = 11;
private static final int EVENT_GET_SPN_DONE = 12;
@@ -147,6 +147,8 @@
private static final int EVENT_GET_CFIS_DONE = 32;
private static final int EVENT_GET_CSP_CPHS_DONE = 33;
+ protected static final int CSIM_EVENT_BASE = 100;
+
// Lookup table for carriers known to produce SIMs which incorrectly indicate MNC length.
private static final String[] MCCMNC_CODES_HAVING_3DIGITS_MNC = {
@@ -1285,7 +1287,7 @@
fetchSimRecords();
}
- private void fetchSimRecords() {
+ protected void fetchSimRecords() {
recordsRequested = true;
IccFileHandler iccFh = phone.getIccFileHandler();