PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/libs/input/PointerController.cpp

https://bitbucket.org/seandroid/frameworks-base
C++ | 607 lines | 452 code | 112 blank | 43 comment | 91 complexity | 7cecc2d4da9a10d130e00678e6dc3efd MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CC0-1.0, BitTorrent-1.0
  1. /*
  2. * Copyright (C) 2010 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #define LOG_TAG "PointerController"
  17. //#define LOG_NDEBUG 0
  18. // Log debug messages about pointer updates
  19. #define DEBUG_POINTER_UPDATES 0
  20. #include "PointerController.h"
  21. #include <cutils/log.h>
  22. #pragma GCC diagnostic push
  23. #pragma GCC diagnostic ignored "-Wunused-parameter"
  24. #include <SkBitmap.h>
  25. #include <SkCanvas.h>
  26. #include <SkColor.h>
  27. #include <SkPaint.h>
  28. #include <SkXfermode.h>
  29. #pragma GCC diagnostic pop
  30. namespace android {
  31. // --- PointerController ---
  32. // Time to wait before starting the fade when the pointer is inactive.
  33. static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
  34. static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
  35. // Time to wait between animation frames.
  36. static const nsecs_t ANIMATION_FRAME_INTERVAL = 1000000000LL / 60;
  37. // Time to spend fading out the spot completely.
  38. static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms
  39. // Time to spend fading out the pointer completely.
  40. static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
  41. // --- PointerController ---
  42. PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
  43. const sp<Looper>& looper, const sp<SpriteController>& spriteController) :
  44. mPolicy(policy), mLooper(looper), mSpriteController(spriteController) {
  45. mHandler = new WeakMessageHandler(this);
  46. AutoMutex _l(mLock);
  47. mLocked.animationPending = false;
  48. mLocked.displayWidth = -1;
  49. mLocked.displayHeight = -1;
  50. mLocked.displayOrientation = DISPLAY_ORIENTATION_0;
  51. mLocked.presentation = PRESENTATION_POINTER;
  52. mLocked.presentationChanged = false;
  53. mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL;
  54. mLocked.pointerFadeDirection = 0;
  55. mLocked.pointerX = 0;
  56. mLocked.pointerY = 0;
  57. mLocked.pointerAlpha = 0.0f; // pointer is initially faded
  58. mLocked.pointerSprite = mSpriteController->createSprite();
  59. mLocked.pointerIconChanged = false;
  60. mLocked.buttonState = 0;
  61. loadResources();
  62. }
  63. PointerController::~PointerController() {
  64. mLooper->removeMessages(mHandler);
  65. AutoMutex _l(mLock);
  66. mLocked.pointerSprite.clear();
  67. for (size_t i = 0; i < mLocked.spots.size(); i++) {
  68. delete mLocked.spots.itemAt(i);
  69. }
  70. mLocked.spots.clear();
  71. mLocked.recycledSprites.clear();
  72. }
  73. bool PointerController::getBounds(float* outMinX, float* outMinY,
  74. float* outMaxX, float* outMaxY) const {
  75. AutoMutex _l(mLock);
  76. return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
  77. }
  78. bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
  79. float* outMaxX, float* outMaxY) const {
  80. if (mLocked.displayWidth <= 0 || mLocked.displayHeight <= 0) {
  81. return false;
  82. }
  83. *outMinX = 0;
  84. *outMinY = 0;
  85. switch (mLocked.displayOrientation) {
  86. case DISPLAY_ORIENTATION_90:
  87. case DISPLAY_ORIENTATION_270:
  88. *outMaxX = mLocked.displayHeight - 1;
  89. *outMaxY = mLocked.displayWidth - 1;
  90. break;
  91. default:
  92. *outMaxX = mLocked.displayWidth - 1;
  93. *outMaxY = mLocked.displayHeight - 1;
  94. break;
  95. }
  96. return true;
  97. }
  98. void PointerController::move(float deltaX, float deltaY) {
  99. #if DEBUG_POINTER_UPDATES
  100. ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
  101. #endif
  102. if (deltaX == 0.0f && deltaY == 0.0f) {
  103. return;
  104. }
  105. AutoMutex _l(mLock);
  106. setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
  107. }
  108. void PointerController::setButtonState(int32_t buttonState) {
  109. #if DEBUG_POINTER_UPDATES
  110. ALOGD("Set button state 0x%08x", buttonState);
  111. #endif
  112. AutoMutex _l(mLock);
  113. if (mLocked.buttonState != buttonState) {
  114. mLocked.buttonState = buttonState;
  115. }
  116. }
  117. int32_t PointerController::getButtonState() const {
  118. AutoMutex _l(mLock);
  119. return mLocked.buttonState;
  120. }
  121. void PointerController::setPosition(float x, float y) {
  122. #if DEBUG_POINTER_UPDATES
  123. ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
  124. #endif
  125. AutoMutex _l(mLock);
  126. setPositionLocked(x, y);
  127. }
  128. void PointerController::setPositionLocked(float x, float y) {
  129. float minX, minY, maxX, maxY;
  130. if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
  131. if (x <= minX) {
  132. mLocked.pointerX = minX;
  133. } else if (x >= maxX) {
  134. mLocked.pointerX = maxX;
  135. } else {
  136. mLocked.pointerX = x;
  137. }
  138. if (y <= minY) {
  139. mLocked.pointerY = minY;
  140. } else if (y >= maxY) {
  141. mLocked.pointerY = maxY;
  142. } else {
  143. mLocked.pointerY = y;
  144. }
  145. updatePointerLocked();
  146. }
  147. }
  148. void PointerController::getPosition(float* outX, float* outY) const {
  149. AutoMutex _l(mLock);
  150. *outX = mLocked.pointerX;
  151. *outY = mLocked.pointerY;
  152. }
  153. void PointerController::fade(Transition transition) {
  154. AutoMutex _l(mLock);
  155. // Remove the inactivity timeout, since we are fading now.
  156. removeInactivityTimeoutLocked();
  157. // Start fading.
  158. if (transition == TRANSITION_IMMEDIATE) {
  159. mLocked.pointerFadeDirection = 0;
  160. mLocked.pointerAlpha = 0.0f;
  161. updatePointerLocked();
  162. } else {
  163. mLocked.pointerFadeDirection = -1;
  164. startAnimationLocked();
  165. }
  166. }
  167. void PointerController::unfade(Transition transition) {
  168. AutoMutex _l(mLock);
  169. // Always reset the inactivity timer.
  170. resetInactivityTimeoutLocked();
  171. // Start unfading.
  172. if (transition == TRANSITION_IMMEDIATE) {
  173. mLocked.pointerFadeDirection = 0;
  174. mLocked.pointerAlpha = 1.0f;
  175. updatePointerLocked();
  176. } else {
  177. mLocked.pointerFadeDirection = 1;
  178. startAnimationLocked();
  179. }
  180. }
  181. void PointerController::setPresentation(Presentation presentation) {
  182. AutoMutex _l(mLock);
  183. if (mLocked.presentation != presentation) {
  184. mLocked.presentation = presentation;
  185. mLocked.presentationChanged = true;
  186. if (presentation != PRESENTATION_SPOT) {
  187. fadeOutAndReleaseAllSpotsLocked();
  188. }
  189. updatePointerLocked();
  190. }
  191. }
  192. void PointerController::setSpots(const PointerCoords* spotCoords,
  193. const uint32_t* spotIdToIndex, BitSet32 spotIdBits) {
  194. #if DEBUG_POINTER_UPDATES
  195. ALOGD("setSpots: idBits=%08x", spotIdBits.value);
  196. for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
  197. uint32_t id = idBits.firstMarkedBit();
  198. idBits.clearBit(id);
  199. const PointerCoords& c = spotCoords[spotIdToIndex[id]];
  200. ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f", id,
  201. c.getAxisValue(AMOTION_EVENT_AXIS_X),
  202. c.getAxisValue(AMOTION_EVENT_AXIS_Y),
  203. c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
  204. }
  205. #endif
  206. AutoMutex _l(mLock);
  207. mSpriteController->openTransaction();
  208. // Add or move spots for fingers that are down.
  209. for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
  210. uint32_t id = idBits.clearFirstMarkedBit();
  211. const PointerCoords& c = spotCoords[spotIdToIndex[id]];
  212. const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0
  213. ? mResources.spotTouch : mResources.spotHover;
  214. float x = c.getAxisValue(AMOTION_EVENT_AXIS_X);
  215. float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
  216. Spot* spot = getSpotLocked(id);
  217. if (!spot) {
  218. spot = createAndAddSpotLocked(id);
  219. }
  220. spot->updateSprite(&icon, x, y);
  221. }
  222. // Remove spots for fingers that went up.
  223. for (size_t i = 0; i < mLocked.spots.size(); i++) {
  224. Spot* spot = mLocked.spots.itemAt(i);
  225. if (spot->id != Spot::INVALID_ID
  226. && !spotIdBits.hasBit(spot->id)) {
  227. fadeOutAndReleaseSpotLocked(spot);
  228. }
  229. }
  230. mSpriteController->closeTransaction();
  231. }
  232. void PointerController::clearSpots() {
  233. #if DEBUG_POINTER_UPDATES
  234. ALOGD("clearSpots");
  235. #endif
  236. AutoMutex _l(mLock);
  237. fadeOutAndReleaseAllSpotsLocked();
  238. }
  239. void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
  240. AutoMutex _l(mLock);
  241. if (mLocked.inactivityTimeout != inactivityTimeout) {
  242. mLocked.inactivityTimeout = inactivityTimeout;
  243. resetInactivityTimeoutLocked();
  244. }
  245. }
  246. void PointerController::setDisplayViewport(int32_t width, int32_t height, int32_t orientation) {
  247. AutoMutex _l(mLock);
  248. // Adjust to use the display's unrotated coordinate frame.
  249. if (orientation == DISPLAY_ORIENTATION_90
  250. || orientation == DISPLAY_ORIENTATION_270) {
  251. int32_t temp = height;
  252. height = width;
  253. width = temp;
  254. }
  255. if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
  256. mLocked.displayWidth = width;
  257. mLocked.displayHeight = height;
  258. float minX, minY, maxX, maxY;
  259. if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
  260. mLocked.pointerX = (minX + maxX) * 0.5f;
  261. mLocked.pointerY = (minY + maxY) * 0.5f;
  262. } else {
  263. mLocked.pointerX = 0;
  264. mLocked.pointerY = 0;
  265. }
  266. fadeOutAndReleaseAllSpotsLocked();
  267. }
  268. if (mLocked.displayOrientation != orientation) {
  269. // Apply offsets to convert from the pixel top-left corner position to the pixel center.
  270. // This creates an invariant frame of reference that we can easily rotate when
  271. // taking into account that the pointer may be located at fractional pixel offsets.
  272. float x = mLocked.pointerX + 0.5f;
  273. float y = mLocked.pointerY + 0.5f;
  274. float temp;
  275. // Undo the previous rotation.
  276. switch (mLocked.displayOrientation) {
  277. case DISPLAY_ORIENTATION_90:
  278. temp = x;
  279. x = mLocked.displayWidth - y;
  280. y = temp;
  281. break;
  282. case DISPLAY_ORIENTATION_180:
  283. x = mLocked.displayWidth - x;
  284. y = mLocked.displayHeight - y;
  285. break;
  286. case DISPLAY_ORIENTATION_270:
  287. temp = x;
  288. x = y;
  289. y = mLocked.displayHeight - temp;
  290. break;
  291. }
  292. // Perform the new rotation.
  293. switch (orientation) {
  294. case DISPLAY_ORIENTATION_90:
  295. temp = x;
  296. x = y;
  297. y = mLocked.displayWidth - temp;
  298. break;
  299. case DISPLAY_ORIENTATION_180:
  300. x = mLocked.displayWidth - x;
  301. y = mLocked.displayHeight - y;
  302. break;
  303. case DISPLAY_ORIENTATION_270:
  304. temp = x;
  305. x = mLocked.displayHeight - y;
  306. y = temp;
  307. break;
  308. }
  309. // Apply offsets to convert from the pixel center to the pixel top-left corner position
  310. // and save the results.
  311. mLocked.pointerX = x - 0.5f;
  312. mLocked.pointerY = y - 0.5f;
  313. mLocked.displayOrientation = orientation;
  314. }
  315. updatePointerLocked();
  316. }
  317. void PointerController::setPointerIcon(const SpriteIcon& icon) {
  318. AutoMutex _l(mLock);
  319. mLocked.pointerIcon = icon.copy();
  320. mLocked.pointerIconChanged = true;
  321. updatePointerLocked();
  322. }
  323. void PointerController::handleMessage(const Message& message) {
  324. switch (message.what) {
  325. case MSG_ANIMATE:
  326. doAnimate();
  327. break;
  328. case MSG_INACTIVITY_TIMEOUT:
  329. doInactivityTimeout();
  330. break;
  331. }
  332. }
  333. void PointerController::doAnimate() {
  334. AutoMutex _l(mLock);
  335. bool keepAnimating = false;
  336. mLocked.animationPending = false;
  337. nsecs_t frameDelay = systemTime(SYSTEM_TIME_MONOTONIC) - mLocked.animationTime;
  338. // Animate pointer fade.
  339. if (mLocked.pointerFadeDirection < 0) {
  340. mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
  341. if (mLocked.pointerAlpha <= 0.0f) {
  342. mLocked.pointerAlpha = 0.0f;
  343. mLocked.pointerFadeDirection = 0;
  344. } else {
  345. keepAnimating = true;
  346. }
  347. updatePointerLocked();
  348. } else if (mLocked.pointerFadeDirection > 0) {
  349. mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
  350. if (mLocked.pointerAlpha >= 1.0f) {
  351. mLocked.pointerAlpha = 1.0f;
  352. mLocked.pointerFadeDirection = 0;
  353. } else {
  354. keepAnimating = true;
  355. }
  356. updatePointerLocked();
  357. }
  358. // Animate spots that are fading out and being removed.
  359. for (size_t i = 0; i < mLocked.spots.size(); i++) {
  360. Spot* spot = mLocked.spots.itemAt(i);
  361. if (spot->id == Spot::INVALID_ID) {
  362. spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
  363. if (spot->alpha <= 0) {
  364. mLocked.spots.removeAt(i--);
  365. releaseSpotLocked(spot);
  366. } else {
  367. spot->sprite->setAlpha(spot->alpha);
  368. keepAnimating = true;
  369. }
  370. }
  371. }
  372. if (keepAnimating) {
  373. startAnimationLocked();
  374. }
  375. }
  376. void PointerController::doInactivityTimeout() {
  377. fade(TRANSITION_GRADUAL);
  378. }
  379. void PointerController::startAnimationLocked() {
  380. if (!mLocked.animationPending) {
  381. mLocked.animationPending = true;
  382. mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
  383. mLooper->sendMessageDelayed(ANIMATION_FRAME_INTERVAL, mHandler, Message(MSG_ANIMATE));
  384. }
  385. }
  386. void PointerController::resetInactivityTimeoutLocked() {
  387. mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
  388. nsecs_t timeout = mLocked.inactivityTimeout == INACTIVITY_TIMEOUT_SHORT
  389. ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
  390. mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT);
  391. }
  392. void PointerController::removeInactivityTimeoutLocked() {
  393. mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
  394. }
  395. void PointerController::updatePointerLocked() {
  396. mSpriteController->openTransaction();
  397. mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
  398. mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
  399. if (mLocked.pointerAlpha > 0) {
  400. mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
  401. mLocked.pointerSprite->setVisible(true);
  402. } else {
  403. mLocked.pointerSprite->setVisible(false);
  404. }
  405. if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
  406. mLocked.pointerSprite->setIcon(mLocked.presentation == PRESENTATION_POINTER
  407. ? mLocked.pointerIcon : mResources.spotAnchor);
  408. mLocked.pointerIconChanged = false;
  409. mLocked.presentationChanged = false;
  410. }
  411. mSpriteController->closeTransaction();
  412. }
  413. PointerController::Spot* PointerController::getSpotLocked(uint32_t id) {
  414. for (size_t i = 0; i < mLocked.spots.size(); i++) {
  415. Spot* spot = mLocked.spots.itemAt(i);
  416. if (spot->id == id) {
  417. return spot;
  418. }
  419. }
  420. return NULL;
  421. }
  422. PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id) {
  423. // Remove spots until we have fewer than MAX_SPOTS remaining.
  424. while (mLocked.spots.size() >= MAX_SPOTS) {
  425. Spot* spot = removeFirstFadingSpotLocked();
  426. if (!spot) {
  427. spot = mLocked.spots.itemAt(0);
  428. mLocked.spots.removeAt(0);
  429. }
  430. releaseSpotLocked(spot);
  431. }
  432. // Obtain a sprite from the recycled pool.
  433. sp<Sprite> sprite;
  434. if (! mLocked.recycledSprites.isEmpty()) {
  435. sprite = mLocked.recycledSprites.top();
  436. mLocked.recycledSprites.pop();
  437. } else {
  438. sprite = mSpriteController->createSprite();
  439. }
  440. // Return the new spot.
  441. Spot* spot = new Spot(id, sprite);
  442. mLocked.spots.push(spot);
  443. return spot;
  444. }
  445. PointerController::Spot* PointerController::removeFirstFadingSpotLocked() {
  446. for (size_t i = 0; i < mLocked.spots.size(); i++) {
  447. Spot* spot = mLocked.spots.itemAt(i);
  448. if (spot->id == Spot::INVALID_ID) {
  449. mLocked.spots.removeAt(i);
  450. return spot;
  451. }
  452. }
  453. return NULL;
  454. }
  455. void PointerController::releaseSpotLocked(Spot* spot) {
  456. spot->sprite->clearIcon();
  457. if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
  458. mLocked.recycledSprites.push(spot->sprite);
  459. }
  460. delete spot;
  461. }
  462. void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
  463. if (spot->id != Spot::INVALID_ID) {
  464. spot->id = Spot::INVALID_ID;
  465. startAnimationLocked();
  466. }
  467. }
  468. void PointerController::fadeOutAndReleaseAllSpotsLocked() {
  469. for (size_t i = 0; i < mLocked.spots.size(); i++) {
  470. Spot* spot = mLocked.spots.itemAt(i);
  471. fadeOutAndReleaseSpotLocked(spot);
  472. }
  473. }
  474. void PointerController::loadResources() {
  475. mPolicy->loadPointerResources(&mResources);
  476. }
  477. // --- PointerController::Spot ---
  478. void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y) {
  479. sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
  480. sprite->setAlpha(alpha);
  481. sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
  482. sprite->setPosition(x, y);
  483. this->x = x;
  484. this->y = y;
  485. if (icon != lastIcon) {
  486. lastIcon = icon;
  487. if (icon) {
  488. sprite->setIcon(*icon);
  489. sprite->setVisible(true);
  490. } else {
  491. sprite->setVisible(false);
  492. }
  493. }
  494. }
  495. } // namespace android