KeyguardWidgetPager.java revision bb5c941149b66c0192736468bb60f47984dd5e1f
1/* 2 * Copyright (C) 2012 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 */ 16package com.android.internal.policy.impl.keyguard; 17 18import android.animation.Animator; 19import android.animation.AnimatorListenerAdapter; 20import android.animation.AnimatorSet; 21import android.animation.ObjectAnimator; 22import android.animation.PropertyValuesHolder; 23import android.animation.TimeInterpolator; 24import android.appwidget.AppWidgetHostView; 25import android.appwidget.AppWidgetProviderInfo; 26import android.content.Context; 27import android.content.res.Resources; 28import android.os.Handler; 29import android.os.HandlerThread; 30import android.util.AttributeSet; 31import android.util.Slog; 32import android.view.Gravity; 33import android.view.MotionEvent; 34import android.view.View; 35import android.view.View.OnLongClickListener; 36import android.view.ViewGroup; 37import android.view.accessibility.AccessibilityEvent; 38import android.view.accessibility.AccessibilityManager; 39import android.widget.FrameLayout; 40 41import com.android.internal.R; 42import com.android.internal.widget.LockPatternUtils; 43 44import java.util.ArrayList; 45 46public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwitchListener, 47 OnLongClickListener { 48 49 ZInterpolator mZInterpolator = new ZInterpolator(0.5f); 50 private static float CAMERA_DISTANCE = 10000; 51 protected static float OVERSCROLL_MAX_ROTATION = 30; 52 private static final boolean PERFORM_OVERSCROLL_ROTATION = true; 53 54 protected KeyguardViewStateManager mViewStateManager; 55 private LockPatternUtils mLockPatternUtils; 56 57 // Related to the fading in / out background outlines 58 private static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375; 59 private static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 75; 60 protected AnimatorSet mChildrenOutlineFadeAnimation; 61 private float mChildrenOutlineAlpha = 0; 62 private float mSidePagesAlpha = 1f; 63 protected int mScreenCenter; 64 private boolean mHasLayout = false; 65 private boolean mHasMeasure = false; 66 boolean showHintsAfterLayout = false; 67 68 private static final long CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT = 30000; 69 private static final String TAG = "KeyguardWidgetPager"; 70 71 private int mPage = 0; 72 private Callbacks mCallbacks; 73 74 private boolean mCameraWidgetEnabled; 75 76 // Background threads to deal with persistence 77 private HandlerThread mBgPersistenceWorkerThread; 78 private Handler mBgPersistenceWorkerHandler; 79 80 public KeyguardWidgetPager(Context context, AttributeSet attrs) { 81 this(context, attrs, 0); 82 } 83 84 public KeyguardWidgetPager(Context context) { 85 this(null, null, 0); 86 } 87 88 public KeyguardWidgetPager(Context context, AttributeSet attrs, int defStyle) { 89 super(context, attrs, defStyle); 90 if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 91 setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); 92 } 93 94 setPageSwitchListener(this); 95 96 Resources r = getResources(); 97 mCameraWidgetEnabled = r.getBoolean(R.bool.kg_enable_camera_default_widget); 98 mBgPersistenceWorkerThread = new HandlerThread("KeyguardWidgetPager Persistence"); 99 mBgPersistenceWorkerThread.start(); 100 mBgPersistenceWorkerHandler = new Handler(mBgPersistenceWorkerThread.getLooper()); 101 } 102 103 @Override 104 protected void onDetachedFromWindow() { 105 super.onDetachedFromWindow(); 106 107 // Clean up the persistence worker thread 108 if (mBgPersistenceWorkerThread != null) { 109 mBgPersistenceWorkerThread.quit(); 110 } 111 } 112 113 public void setViewStateManager(KeyguardViewStateManager viewStateManager) { 114 mViewStateManager = viewStateManager; 115 } 116 117 public void setLockPatternUtils(LockPatternUtils l) { 118 mLockPatternUtils = l; 119 } 120 121 @Override 122 public void onPageSwitching(View newPage, int newPageIndex) { 123 if (mViewStateManager != null) { 124 mViewStateManager.onPageSwitching(newPage, newPageIndex); 125 } 126 } 127 128 @Override 129 public void onPageSwitched(View newPage, int newPageIndex) { 130 boolean showingStatusWidget = false; 131 if (newPage instanceof ViewGroup) { 132 ViewGroup vg = (ViewGroup) newPage; 133 if (vg.getChildAt(0) instanceof KeyguardStatusView) { 134 showingStatusWidget = true; 135 } 136 } 137 138 // Disable the status bar clock if we're showing the default status widget 139 if (showingStatusWidget) { 140 setSystemUiVisibility(getSystemUiVisibility() | View.STATUS_BAR_DISABLE_CLOCK); 141 } else { 142 setSystemUiVisibility(getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK); 143 } 144 145 // Extend the display timeout if the user switches pages 146 if (mPage != newPageIndex) { 147 int oldPageIndex = mPage; 148 mPage = newPageIndex; 149 userActivity(); 150 KeyguardWidgetFrame oldWidgetPage = getWidgetPageAt(oldPageIndex); 151 if (oldWidgetPage != null) { 152 oldWidgetPage.onActive(false); 153 } 154 KeyguardWidgetFrame newWidgetPage = getWidgetPageAt(newPageIndex); 155 if (newWidgetPage != null) { 156 newWidgetPage.onActive(true); 157 newWidgetPage.requestAccessibilityFocus(); 158 } 159 if (mParent != null && AccessibilityManager.getInstance(mContext).isEnabled()) { 160 AccessibilityEvent event = AccessibilityEvent.obtain( 161 AccessibilityEvent.TYPE_VIEW_SCROLLED); 162 onInitializeAccessibilityEvent(event); 163 onPopulateAccessibilityEvent(event); 164 mParent.requestSendAccessibilityEvent(this, event); 165 } 166 } 167 if (mViewStateManager != null) { 168 mViewStateManager.onPageSwitched(newPage, newPageIndex); 169 } 170 } 171 172 @Override 173 public void sendAccessibilityEvent(int eventType) { 174 if (eventType != AccessibilityEvent.TYPE_VIEW_SCROLLED || isPageMoving()) { 175 super.sendAccessibilityEvent(eventType); 176 } 177 } 178 179 private void userActivity() { 180 if (mCallbacks != null) { 181 mCallbacks.onUserActivityTimeoutChanged(); 182 mCallbacks.userActivity(); 183 } 184 } 185 186 @Override 187 public boolean onTouchEvent(MotionEvent ev) { 188 KeyguardWidgetFrame currentWidgetPage = getWidgetPageAt(getCurrentPage()); 189 if (currentWidgetPage != null && currentWidgetPage.onUserInteraction(ev)) { 190 return true; 191 } 192 return super.onTouchEvent(ev); 193 } 194 195 public void showPagingFeedback() { 196 // Nothing yet. 197 } 198 199 public long getUserActivityTimeout() { 200 View page = getPageAt(mPage); 201 if (page instanceof ViewGroup) { 202 ViewGroup vg = (ViewGroup) page; 203 View view = vg.getChildAt(0); 204 if (!(view instanceof KeyguardStatusView) 205 && !(view instanceof KeyguardMultiUserSelectorView)) { 206 return CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT; 207 } 208 } 209 return -1; 210 } 211 212 public void setCallbacks(Callbacks callbacks) { 213 mCallbacks = callbacks; 214 } 215 216 public interface Callbacks { 217 public void userActivity(); 218 public void onUserActivityTimeoutChanged(); 219 } 220 221 public void addWidget(View widget) { 222 addWidget(widget, -1); 223 } 224 225 226 public void onRemoveView(View v) { 227 final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId(); 228 mBgPersistenceWorkerHandler.post(new Runnable() { 229 @Override 230 public void run() { 231 mLockPatternUtils.removeAppWidget(appWidgetId); 232 } 233 }); 234 } 235 236 public void onAddView(View v, final int index) { 237 final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId(); 238 final int[] pagesRange = new int[mTempVisiblePagesRange.length]; 239 getVisiblePages(pagesRange); 240 boundByReorderablePages(true, pagesRange); 241 // Subtract from the index to take into account pages before the reorderable 242 // pages (e.g. the "add widget" page) 243 mBgPersistenceWorkerHandler.post(new Runnable() { 244 @Override 245 public void run() { 246 mLockPatternUtils.addAppWidget(appWidgetId, index - pagesRange[0]); 247 } 248 }); 249 } 250 251 /* 252 * We wrap widgets in a special frame which handles drawing the over scroll foreground. 253 */ 254 public void addWidget(View widget, int pageIndex) { 255 KeyguardWidgetFrame frame; 256 // All views contained herein should be wrapped in a KeyguardWidgetFrame 257 if (!(widget instanceof KeyguardWidgetFrame)) { 258 frame = new KeyguardWidgetFrame(getContext()); 259 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, 260 LayoutParams.MATCH_PARENT); 261 lp.gravity = Gravity.TOP; 262 263 // The framework adds a default padding to AppWidgetHostView. We don't need this padding 264 // for the Keyguard, so we override it to be 0. 265 widget.setPadding(0, 0, 0, 0); 266 frame.addView(widget, lp); 267 268 // We set whether or not this widget supports vertical resizing. 269 if (widget instanceof AppWidgetHostView) { 270 AppWidgetHostView awhv = (AppWidgetHostView) widget; 271 AppWidgetProviderInfo info = awhv.getAppWidgetInfo(); 272 if ((info.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0) { 273 frame.setWidgetLockedSmall(false); 274 } else { 275 // Lock the widget to be small. 276 frame.setWidgetLockedSmall(true); 277 } 278 } 279 } else { 280 frame = (KeyguardWidgetFrame) widget; 281 } 282 283 ViewGroup.LayoutParams pageLp = new ViewGroup.LayoutParams( 284 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 285 frame.setOnLongClickListener(this); 286 287 if (pageIndex == -1) { 288 addView(frame, pageLp); 289 } else { 290 addView(frame, pageIndex, pageLp); 291 } 292 293 // Update the frame content description. 294 View content = (widget == frame) ? frame.getContent() : widget; 295 if (content != null) { 296 String contentDescription = mContext.getString( 297 com.android.internal.R.string.keyguard_accessibility_widget, 298 content.getContentDescription()); 299 frame.setContentDescription(contentDescription); 300 } 301 } 302 303 /** 304 * Use addWidget() instead. 305 * @deprecated 306 */ 307 @Override 308 public void addView(View child, int index) { 309 enforceKeyguardWidgetFrame(child); 310 super.addView(child, index); 311 } 312 313 /** 314 * Use addWidget() instead. 315 * @deprecated 316 */ 317 @Override 318 public void addView(View child, int width, int height) { 319 enforceKeyguardWidgetFrame(child); 320 super.addView(child, width, height); 321 } 322 323 /** 324 * Use addWidget() instead. 325 * @deprecated 326 */ 327 @Override 328 public void addView(View child, LayoutParams params) { 329 enforceKeyguardWidgetFrame(child); 330 super.addView(child, params); 331 } 332 333 /** 334 * Use addWidget() instead. 335 * @deprecated 336 */ 337 @Override 338 public void addView(View child, int index, LayoutParams params) { 339 enforceKeyguardWidgetFrame(child); 340 super.addView(child, index, params); 341 } 342 343 private void enforceKeyguardWidgetFrame(View child) { 344 if (!(child instanceof KeyguardWidgetFrame)) { 345 throw new IllegalArgumentException( 346 "KeyguardWidgetPager children must be KeyguardWidgetFrames"); 347 } 348 } 349 350 public KeyguardWidgetFrame getWidgetPageAt(int index) { 351 // This is always a valid cast as we've guarded the ability to 352 return (KeyguardWidgetFrame) getChildAt(index); 353 } 354 355 protected void onUnhandledTap(MotionEvent ev) { 356 showPagingFeedback(); 357 } 358 359 @Override 360 protected void onPageBeginMoving() { 361 if (mViewStateManager != null) { 362 mViewStateManager.onPageBeginMoving(); 363 } 364 if (!isReordering(false)) { 365 showOutlinesAndSidePages(); 366 } 367 userActivity(); 368 } 369 370 @Override 371 protected void onPageEndMoving() { 372 if (mViewStateManager != null) { 373 mViewStateManager.onPageEndMoving(); 374 } 375 376 // In the reordering case, the pages will be faded appropriately on completion 377 // of the zoom in animation. 378 if (!isReordering(false)) { 379 hideOutlinesAndSidePages(); 380 } 381 } 382 383 protected void enablePageLayers() { 384 int children = getChildCount(); 385 for (int i = 0; i < children; i++) { 386 getWidgetPageAt(i).enableHardwareLayersForContent(); 387 } 388 } 389 390 protected void disablePageLayers() { 391 int children = getChildCount(); 392 for (int i = 0; i < children; i++) { 393 getWidgetPageAt(i).disableHardwareLayersForContent(); 394 } 395 } 396 397 /* 398 * This interpolator emulates the rate at which the perceived scale of an object changes 399 * as its distance from a camera increases. When this interpolator is applied to a scale 400 * animation on a view, it evokes the sense that the object is shrinking due to moving away 401 * from the camera. 402 */ 403 static class ZInterpolator implements TimeInterpolator { 404 private float focalLength; 405 406 public ZInterpolator(float foc) { 407 focalLength = foc; 408 } 409 410 public float getInterpolation(float input) { 411 return (1.0f - focalLength / (focalLength + input)) / 412 (1.0f - focalLength / (focalLength + 1.0f)); 413 } 414 } 415 416 @Override 417 protected void overScroll(float amount) { 418 acceleratedOverScroll(amount); 419 } 420 421 float backgroundAlphaInterpolator(float r) { 422 return Math.min(1f, r); 423 } 424 425 private void updatePageAlphaValues(int screenCenter) { 426 } 427 428 public float getAlphaForPage(int screenCenter, int index) { 429 return 1f; 430 } 431 432 public float getOutlineAlphaForPage(int screenCenter, int index) { 433 return getAlphaForPage(screenCenter, index) * KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER; 434 } 435 436 protected boolean isOverScrollChild(int index, float scrollProgress) { 437 boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX; 438 return (isInOverscroll && (index == 0 && scrollProgress < 0 || 439 index == getChildCount() - 1 && scrollProgress > 0)); 440 } 441 442 @Override 443 protected void screenScrolled(int screenCenter) { 444 mScreenCenter = screenCenter; 445 updatePageAlphaValues(screenCenter); 446 for (int i = 0; i < getChildCount(); i++) { 447 KeyguardWidgetFrame v = getWidgetPageAt(i); 448 if (v == mDragView) continue; 449 if (v != null) { 450 float scrollProgress = getScrollProgress(screenCenter, v, i); 451 452 v.setCameraDistance(mDensity * CAMERA_DISTANCE); 453 454 if (isOverScrollChild(i, scrollProgress) && PERFORM_OVERSCROLL_ROTATION) { 455 v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress); 456 v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0); 457 } else { 458 v.setRotationY(0f); 459 v.setOverScrollAmount(0, false); 460 } 461 462 float alpha = v.getAlpha(); 463 // If the view has 0 alpha, we set it to be invisible so as to prevent 464 // it from accepting touches 465 if (alpha == 0) { 466 v.setVisibility(INVISIBLE); 467 } else if (v.getVisibility() != VISIBLE) { 468 v.setVisibility(VISIBLE); 469 } 470 } 471 } 472 } 473 474 @Override 475 void boundByReorderablePages(boolean isReordering, int[] range) { 476 if (isReordering) { 477 if (isAddWidgetPageVisible()) { 478 range[0]++; 479 } 480 if (isMusicWidgetVisible()) { 481 range[1]--; 482 } 483 if (isCameraWidgetVisible()) { 484 range[1]--; 485 } 486 } 487 } 488 489 /* 490 * Special widgets 491 */ 492 boolean isAddWidgetPageVisible() { 493 // TODO: Make proper test once we decide whether the add-page is always showing 494 return true; 495 } 496 boolean isMusicWidgetVisible() { 497 return mViewStateManager.getTransportState() != KeyguardViewStateManager.TRANSPORT_GONE; 498 } 499 boolean isCameraWidgetVisible() { 500 return mCameraWidgetEnabled; 501 } 502 503 protected void reorderStarting() { 504 showOutlinesAndSidePages(); 505 } 506 507 @Override 508 protected void onStartReordering() { 509 super.onStartReordering(); 510 enablePageLayers(); 511 reorderStarting(); 512 } 513 514 @Override 515 protected void onEndReordering() { 516 super.onEndReordering(); 517 hideOutlinesAndSidePages(); 518 } 519 520 void showOutlinesAndSidePages() { 521 animateOutlinesAndSidePages(true); 522 } 523 524 void hideOutlinesAndSidePages() { 525 animateOutlinesAndSidePages(false); 526 } 527 528 public void showInitialPageHints() { 529 if (mHasLayout) { 530 showOutlinesAndSidePages(); 531 } else { 532 // The layout hints depend on layout being run once 533 showHintsAfterLayout = true; 534 } 535 } 536 537 @Override 538 public void onAttachedToWindow() { 539 super.onAttachedToWindow(); 540 mHasMeasure = false; 541 mHasLayout = false; 542 } 543 544 @Override 545 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 546 super.onLayout(changed, left, top, right, bottom); 547 if (showHintsAfterLayout) { 548 post(new Runnable() { 549 @Override 550 public void run() { 551 showOutlinesAndSidePages(); 552 } 553 }); 554 showHintsAfterLayout = false; 555 } 556 mHasLayout = true; 557 } 558 559 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 560 int maxChallengeTop = -1; 561 View parent = (View) getParent(); 562 boolean challengeShowing = false; 563 // Widget pages need to know where the top of the sliding challenge is so that they 564 // now how big the widget should be when the challenge is up. We compute it here and 565 // then propagate it to each of our children. 566 if (parent.getParent() instanceof SlidingChallengeLayout) { 567 SlidingChallengeLayout scl = (SlidingChallengeLayout) parent.getParent(); 568 int top = scl.getMaxChallengeTop(); 569 570 // This is a bit evil, but we need to map a coordinate relative to the SCL into a 571 // coordinate relative to our children, hence we subtract the top padding.s 572 maxChallengeTop = top - getPaddingTop(); 573 challengeShowing = scl.isChallengeShowing(); 574 575 int count = getChildCount(); 576 for (int i = 0; i < count; i++) { 577 KeyguardWidgetFrame frame = getWidgetPageAt(i); 578 frame.setMaxChallengeTop(maxChallengeTop); 579 // On the very first measure pass, if the challenge is showing, we need to make sure 580 // that the widget on the current page is small. 581 if (challengeShowing && i == mCurrentPage && !mHasMeasure) { 582 frame.shrinkWidget(); 583 } 584 } 585 } 586 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 587 mHasMeasure = true; 588 } 589 590 void animateOutlinesAndSidePages(final boolean show) { 591 animateOutlinesAndSidePages(show, -1); 592 } 593 594 void animateOutlinesAndSidePages(final boolean show, int duration) { 595 if (mChildrenOutlineFadeAnimation != null) { 596 mChildrenOutlineFadeAnimation.cancel(); 597 mChildrenOutlineFadeAnimation = null; 598 } 599 int count = getChildCount(); 600 PropertyValuesHolder alpha; 601 ArrayList<Animator> anims = new ArrayList<Animator>(); 602 603 if (duration == -1) { 604 duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION : 605 CHILDREN_OUTLINE_FADE_OUT_DURATION; 606 } 607 608 int curPage = getNextPage(); 609 for (int i = 0; i < count; i++) { 610 float finalContentAlpha; 611 if (show) { 612 finalContentAlpha = getAlphaForPage(mScreenCenter, i); 613 } else if (!show && i == curPage) { 614 finalContentAlpha = 1f; 615 } else { 616 finalContentAlpha = 0f; 617 } 618 KeyguardWidgetFrame child = getWidgetPageAt(i); 619 alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalContentAlpha); 620 ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha); 621 anims.add(a); 622 623 float finalOutlineAlpha = show ? getOutlineAlphaForPage(mScreenCenter, i) : 0f; 624 child.fadeFrame(this, show, finalOutlineAlpha, duration); 625 } 626 627 mChildrenOutlineFadeAnimation = new AnimatorSet(); 628 mChildrenOutlineFadeAnimation.playTogether(anims); 629 630 mChildrenOutlineFadeAnimation.setDuration(duration); 631 mChildrenOutlineFadeAnimation.addListener(new AnimatorListenerAdapter() { 632 @Override 633 public void onAnimationStart(Animator animation) { 634 if (show) { 635 enablePageLayers(); 636 } 637 } 638 @Override 639 public void onAnimationEnd(Animator animation) { 640 if (!show) { 641 disablePageLayers(); 642 } 643 } 644 }); 645 mChildrenOutlineFadeAnimation.start(); 646 } 647 648 public void setChildrenOutlineAlpha(float alpha) { 649 mChildrenOutlineAlpha = alpha; 650 for (int i = 0; i < getChildCount(); i++) { 651 getWidgetPageAt(i).setBackgroundAlpha(alpha); 652 } 653 } 654 655 public void setSidePagesAlpha(float alpha) { 656 // This gives the current page, or the destination page if in transit. 657 int curPage = getNextPage(); 658 mSidePagesAlpha = alpha; 659 for (int i = 0; i < getChildCount(); i++) { 660 if (curPage != i) { 661 getWidgetPageAt(i).setContentAlpha(alpha); 662 } else { 663 // We lock the current page alpha to 1. 664 getWidgetPageAt(i).setContentAlpha(1.0f); 665 } 666 } 667 } 668 669 public void setChildrenOutlineMultiplier(float alpha) { 670 mChildrenOutlineAlpha = alpha; 671 for (int i = 0; i < getChildCount(); i++) { 672 getWidgetPageAt(i).setBackgroundAlphaMultiplier(alpha); 673 } 674 } 675 676 public float getSidePagesAlpha() { 677 return mSidePagesAlpha; 678 } 679 680 public float getChildrenOutlineAlpha() { 681 return mChildrenOutlineAlpha; 682 } 683 684 @Override 685 public boolean onLongClick(View v) { 686 // Disallow long pressing to reorder if the challenge is showing 687 boolean isChallengeOverlapping = mViewStateManager.isChallengeShowing() && 688 mViewStateManager.isChallengeOverlapping(); 689 if (!isChallengeOverlapping && startReordering()) { 690 return true; 691 } 692 return false; 693 } 694 695 public void removeWidget(View view) { 696 if (view instanceof KeyguardWidgetFrame) { 697 removeView(view); 698 } else { 699 // Assume view was wrapped by a KeyguardWidgetFrame in KeyguardWidgetPager#addWidget(). 700 // This supports legacy hard-coded "widgets" like KeyguardTransportControlView. 701 int pos = getWidgetPageIndex(view); 702 if (pos != -1) { 703 KeyguardWidgetFrame frame = (KeyguardWidgetFrame) getChildAt(pos); 704 frame.removeView(view); 705 removeView(frame); 706 } else { 707 Slog.w(TAG, "removeWidget() can't find:" + view); 708 } 709 } 710 } 711 712 public int getWidgetPageIndex(View view) { 713 if (view instanceof KeyguardWidgetFrame) { 714 return indexOfChild(view); 715 } else { 716 // View was wrapped by a KeyguardWidgetFrame by KeyguardWidgetPager#addWidget() 717 return indexOfChild((KeyguardWidgetFrame)view.getParent()); 718 } 719 } 720} 721