blob: 66903fa531e083885b55514b78d4ef7fa472f8de [file] [log] [blame]
Selim Cinekaa9db1f2018-02-27 17:35:47 -08001/*
2 * Copyright (C) 2018 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
17package com.android.systemui.statusbar.phone;
18
felkachang3d00f352018-05-22 12:53:50 +080019import android.graphics.Point;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080020import android.graphics.Rect;
felkachang7749c9a2018-06-11 15:56:15 +080021import android.view.DisplayCutout;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080022import android.view.View;
felkachang3d00f352018-05-22 12:53:50 +080023import android.view.WindowInsets;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080024
25import com.android.internal.annotations.VisibleForTesting;
Peter Caia8178f52019-05-22 13:01:01 +080026import com.android.internal.widget.ViewClippingUtil;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080027import com.android.systemui.Dependency;
28import com.android.systemui.R;
Beverly1be62f42018-12-19 17:17:48 -050029import com.android.systemui.plugins.DarkIconDispatcher;
Selim Cinekd03518c2018-03-15 12:13:51 -070030import com.android.systemui.statusbar.CrossFadeHelper;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080031import com.android.systemui.statusbar.HeadsUpStatusBarView;
Ned Burnsf81c4c42019-01-07 14:10:43 -050032import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Gus Prevasab336792018-11-14 13:52:20 -050033import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
34import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080035import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080036
Selim Cinek60ffea62018-03-22 13:16:44 -070037import java.util.function.BiConsumer;
38import java.util.function.Consumer;
39
Selim Cinekaa9db1f2018-02-27 17:35:47 -080040/**
41 * Controls the appearance of heads up notifications in the icon area and the header itself.
42 */
Selim Cinekf0c79e12018-05-14 17:17:31 -070043public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
Selim Cinekaa9db1f2018-02-27 17:35:47 -080044 DarkIconDispatcher.DarkReceiver {
Selim Cinekd03518c2018-03-15 12:13:51 -070045 public static final int CONTENT_FADE_DURATION = 110;
46 public static final int CONTENT_FADE_DELAY = 100;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080047 private final NotificationIconAreaController mNotificationIconAreaController;
48 private final HeadsUpManagerPhone mHeadsUpManager;
49 private final NotificationStackScrollLayout mStackScroller;
50 private final HeadsUpStatusBarView mHeadsUpStatusBarView;
Beverly40770652019-02-15 15:49:49 -050051 private final View mCenteredIconView;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080052 private final View mClockView;
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +090053 private final View mOperatorNameView;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080054 private final DarkIconDispatcher mDarkIconDispatcher;
Selim Cinek60ffea62018-03-22 13:16:44 -070055 private final NotificationPanelView mPanelView;
56 private final Consumer<ExpandableNotificationRow>
57 mSetTrackingHeadsUp = this::setTrackingHeadsUp;
58 private final Runnable mUpdatePanelTranslation = this::updatePanelTranslation;
59 private final BiConsumer<Float, Float> mSetExpandedHeight = this::setExpandedHeight;
felkachange6c03a02018-05-24 15:38:04 +080060 @VisibleForTesting
61 float mExpandedHeight;
62 @VisibleForTesting
63 boolean mIsExpanded;
64 @VisibleForTesting
65 float mExpandFraction;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080066 private ExpandableNotificationRow mTrackedChild;
67 private boolean mShown;
Selim Cinek60ffea62018-03-22 13:16:44 -070068 private final View.OnLayoutChangeListener mStackScrollLayoutChangeListener =
69 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom)
70 -> updatePanelTranslation();
Peter Caia8178f52019-05-22 13:01:01 +080071 private final ViewClippingUtil.ClippingParameters mParentClippingParams =
72 new ViewClippingUtil.ClippingParameters() {
73 @Override
74 public boolean shouldFinish(View view) {
75 return view.getId() == R.id.status_bar;
76 }
77 };
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +090078 private boolean mAnimationsEnabled = true;
felkachang3d00f352018-05-22 12:53:50 +080079 Point mPoint;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080080
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +090081
Selim Cinekaa9db1f2018-02-27 17:35:47 -080082 public HeadsUpAppearanceController(
83 NotificationIconAreaController notificationIconAreaController,
84 HeadsUpManagerPhone headsUpManager,
85 View statusbarView) {
86 this(notificationIconAreaController, headsUpManager,
87 statusbarView.findViewById(R.id.heads_up_status_bar_view),
88 statusbarView.findViewById(R.id.notification_stack_scroller),
89 statusbarView.findViewById(R.id.notification_panel),
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +090090 statusbarView.findViewById(R.id.clock),
Beverly40770652019-02-15 15:49:49 -050091 statusbarView.findViewById(R.id.operator_name_frame),
92 statusbarView.findViewById(R.id.centered_icon_area));
Selim Cinekaa9db1f2018-02-27 17:35:47 -080093 }
94
95 @VisibleForTesting
96 public HeadsUpAppearanceController(
97 NotificationIconAreaController notificationIconAreaController,
98 HeadsUpManagerPhone headsUpManager,
99 HeadsUpStatusBarView headsUpStatusBarView,
100 NotificationStackScrollLayout stackScroller,
101 NotificationPanelView panelView,
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +0900102 View clockView,
Beverly40770652019-02-15 15:49:49 -0500103 View operatorNameView,
104 View centeredIconView) {
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800105 mNotificationIconAreaController = notificationIconAreaController;
106 mHeadsUpManager = headsUpManager;
107 mHeadsUpManager.addListener(this);
108 mHeadsUpStatusBarView = headsUpStatusBarView;
Beverly40770652019-02-15 15:49:49 -0500109 mCenteredIconView = centeredIconView;
Selim Cinek332c23f2018-03-16 17:37:50 -0700110 headsUpStatusBarView.setOnDrawingRectChangedListener(
111 () -> updateIsolatedIconLocation(true /* requireUpdate */));
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800112 mStackScroller = stackScroller;
Selim Cinek60ffea62018-03-22 13:16:44 -0700113 mPanelView = panelView;
114 panelView.addTrackingHeadsUpListener(mSetTrackingHeadsUp);
115 panelView.addVerticalTranslationListener(mUpdatePanelTranslation);
Selim Cinek332c23f2018-03-16 17:37:50 -0700116 panelView.setHeadsUpAppearanceController(this);
Selim Cinek60ffea62018-03-22 13:16:44 -0700117 mStackScroller.addOnExpandedHeightListener(mSetExpandedHeight);
118 mStackScroller.addOnLayoutChangeListener(mStackScrollLayoutChangeListener);
Selim Cinekf0c79e12018-05-14 17:17:31 -0700119 mStackScroller.setHeadsUpAppearanceController(this);
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800120 mClockView = clockView;
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +0900121 mOperatorNameView = operatorNameView;
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800122 mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
123 mDarkIconDispatcher.addDarkReceiver(this);
felkachange6c03a02018-05-24 15:38:04 +0800124
125 mHeadsUpStatusBarView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
126 @Override
127 public void onLayoutChange(View v, int left, int top, int right, int bottom,
128 int oldLeft, int oldTop, int oldRight, int oldBottom) {
129 if (shouldBeVisible()) {
130 updateTopEntry();
131
132 // trigger scroller to notify the latest panel translation
133 mStackScroller.requestLayout();
134 }
135 mHeadsUpStatusBarView.removeOnLayoutChangeListener(this);
136 }
137 });
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800138 }
139
Selim Cinek60ffea62018-03-22 13:16:44 -0700140
141 public void destroy() {
142 mHeadsUpManager.removeListener(this);
143 mHeadsUpStatusBarView.setOnDrawingRectChangedListener(null);
144 mPanelView.removeTrackingHeadsUpListener(mSetTrackingHeadsUp);
145 mPanelView.removeVerticalTranslationListener(mUpdatePanelTranslation);
146 mPanelView.setHeadsUpAppearanceController(null);
147 mStackScroller.removeOnExpandedHeightListener(mSetExpandedHeight);
148 mStackScroller.removeOnLayoutChangeListener(mStackScrollLayoutChangeListener);
149 mDarkIconDispatcher.removeDarkReceiver(this);
150 }
151
Selim Cinek332c23f2018-03-16 17:37:50 -0700152 private void updateIsolatedIconLocation(boolean requireStateUpdate) {
153 mNotificationIconAreaController.setIsolatedIconLocation(
154 mHeadsUpStatusBarView.getIconDrawingRect(), requireStateUpdate);
155 }
156
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800157 @Override
Ned Burnsf81c4c42019-01-07 14:10:43 -0500158 public void onHeadsUpPinned(NotificationEntry entry) {
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800159 updateTopEntry();
Evan Laird94492852018-10-25 13:43:01 -0400160 updateHeader(entry);
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800161 }
162
felkachang3d00f352018-05-22 12:53:50 +0800163 /** To count the distance from the window right boundary to scroller right boundary. The
164 * distance formula is the following:
165 * Y = screenSize - (SystemWindow's width + Scroller.getRight())
166 * There are four modes MUST to be considered in Cut Out of RTL.
167 * No Cut Out:
168 * Scroller + NB
169 * NB + Scroller
170 * => SystemWindow = NavigationBar's width
171 * => Y = screenSize - (SystemWindow's width + Scroller.getRight())
172 * Corner Cut Out or Tall Cut Out:
173 * cut out + Scroller + NB
174 * NB + Scroller + cut out
175 * => SystemWindow = NavigationBar's width
176 * => Y = screenSize - (SystemWindow's width + Scroller.getRight())
177 * Double Cut Out:
178 * cut out left + Scroller + (NB + cut out right)
179 * SystemWindow = NavigationBar's width + cut out right width
180 * => Y = screenSize - (SystemWindow's width + Scroller.getRight())
181 * (cut out left + NB) + Scroller + cut out right
182 * SystemWindow = NavigationBar's width + cut out left width
183 * => Y = screenSize - (SystemWindow's width + Scroller.getRight())
184 * @return the translation X value for RTL. In theory, it should be negative. i.e. -Y
185 */
186 private int getRtlTranslation() {
felkachang3d00f352018-05-22 12:53:50 +0800187 if (mPoint == null) {
188 mPoint = new Point();
189 }
190
191 int realDisplaySize = 0;
192 if (mStackScroller.getDisplay() != null) {
193 mStackScroller.getDisplay().getRealSize(mPoint);
194 realDisplaySize = mPoint.x;
195 }
196
197 WindowInsets windowInset = mStackScroller.getRootWindowInsets();
felkachang7749c9a2018-06-11 15:56:15 +0800198 DisplayCutout cutout = (windowInset != null) ? windowInset.getDisplayCutout() : null;
199 int sysWinLeft = (windowInset != null) ? windowInset.getStableInsetLeft() : 0;
200 int sysWinRight = (windowInset != null) ? windowInset.getStableInsetRight() : 0;
201 int cutoutLeft = (cutout != null) ? cutout.getSafeInsetLeft() : 0;
202 int cutoutRight = (cutout != null) ? cutout.getSafeInsetRight() : 0;
203 int leftInset = Math.max(sysWinLeft, cutoutLeft);
204 int rightInset = Math.max(sysWinRight, cutoutRight);
205
206 return leftInset + mStackScroller.getRight() + rightInset - realDisplaySize;
felkachang3d00f352018-05-22 12:53:50 +0800207 }
208
Selim Cinek332c23f2018-03-16 17:37:50 -0700209 public void updatePanelTranslation() {
felkachang3d00f352018-05-22 12:53:50 +0800210 float newTranslation;
211 if (mStackScroller.isLayoutRtl()) {
212 newTranslation = getRtlTranslation();
213 } else {
214 newTranslation = mStackScroller.getLeft();
215 }
216 newTranslation += mStackScroller.getTranslationX();
felkachange8a35362018-05-18 20:11:38 +0800217 mHeadsUpStatusBarView.setPanelTranslation(newTranslation);
Selim Cinek332c23f2018-03-16 17:37:50 -0700218 }
219
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800220 private void updateTopEntry() {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500221 NotificationEntry newEntry = null;
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800222 if (!mIsExpanded && mHeadsUpManager.hasPinnedHeadsUp()) {
223 newEntry = mHeadsUpManager.getTopEntry();
224 }
Ned Burnsf81c4c42019-01-07 14:10:43 -0500225 NotificationEntry previousEntry = mHeadsUpStatusBarView.getShowingEntry();
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800226 mHeadsUpStatusBarView.setEntry(newEntry);
227 if (newEntry != previousEntry) {
Selim Cinekd03518c2018-03-15 12:13:51 -0700228 boolean animateIsolation = false;
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800229 if (newEntry == null) {
230 // no heads up anymore, lets start the disappear animation
231
232 setShown(false);
Selim Cinekd03518c2018-03-15 12:13:51 -0700233 animateIsolation = !mIsExpanded;
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800234 } else if (previousEntry == null) {
235 // We now have a headsUp and didn't have one before. Let's start the disappear
236 // animation
237 setShown(true);
Selim Cinek332c23f2018-03-16 17:37:50 -0700238 animateIsolation = !mIsExpanded;
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800239 }
Selim Cinek332c23f2018-03-16 17:37:50 -0700240 updateIsolatedIconLocation(false /* requireUpdate */);
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800241 mNotificationIconAreaController.showIconIsolated(newEntry == null ? null
Selim Cinek332c23f2018-03-16 17:37:50 -0700242 : newEntry.icon, animateIsolation);
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800243 }
244 }
245
246 private void setShown(boolean isShown) {
Selim Cinekd03518c2018-03-15 12:13:51 -0700247 if (mShown != isShown) {
248 mShown = isShown;
249 if (isShown) {
Peter Caia8178f52019-05-22 13:01:01 +0800250 updateParentClipping(false /* shouldClip */);
Selim Cinekd03518c2018-03-15 12:13:51 -0700251 mHeadsUpStatusBarView.setVisibility(View.VISIBLE);
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +0900252 show(mHeadsUpStatusBarView);
253 hide(mClockView, View.INVISIBLE);
Beverly40770652019-02-15 15:49:49 -0500254 if (mCenteredIconView.getVisibility() != View.GONE) {
255 hide(mCenteredIconView, View.INVISIBLE);
256 }
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +0900257 if (mOperatorNameView != null) {
258 hide(mOperatorNameView, View.INVISIBLE);
259 }
Selim Cinekd03518c2018-03-15 12:13:51 -0700260 } else {
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +0900261 show(mClockView);
Beverly40770652019-02-15 15:49:49 -0500262 if (mCenteredIconView.getVisibility() != View.GONE) {
263 show(mCenteredIconView);
264 }
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +0900265 if (mOperatorNameView != null) {
266 show(mOperatorNameView);
267 }
Peter Caia8178f52019-05-22 13:01:01 +0800268 hide(mHeadsUpStatusBarView, View.GONE, () -> {
269 updateParentClipping(true /* shouldClip */);
270 });
Selim Cinekd03518c2018-03-15 12:13:51 -0700271 }
272 }
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800273 }
274
Peter Caia8178f52019-05-22 13:01:01 +0800275 private void updateParentClipping(boolean shouldClip) {
276 ViewClippingUtil.setClippingDeactivated(
277 mHeadsUpStatusBarView, !shouldClip, mParentClippingParams);
278 }
279
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +0900280 /**
281 * Hides the view and sets the state to endState when finished.
282 *
283 * @param view The view to hide.
284 * @param endState One of {@link View#INVISIBLE} or {@link View#GONE}.
Peter Caia8178f52019-05-22 13:01:01 +0800285 * @see HeadsUpAppearanceController#hide(View, int, Runnable)
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +0900286 * @see View#setVisibility(int)
287 *
288 */
289 private void hide(View view, int endState) {
Peter Caia8178f52019-05-22 13:01:01 +0800290 hide(view, endState, null);
291 }
292
293 /**
294 * Hides the view and sets the state to endState when finished.
295 *
296 * @param view The view to hide.
297 * @param endState One of {@link View#INVISIBLE} or {@link View#GONE}.
298 * @param callback Runnable to be executed after the view has been hidden.
299 * @see View#setVisibility(int)
300 *
301 */
302 private void hide(View view, int endState, Runnable callback) {
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +0900303 if (mAnimationsEnabled) {
304 CrossFadeHelper.fadeOut(view, CONTENT_FADE_DURATION /* duration */,
Peter Caia8178f52019-05-22 13:01:01 +0800305 0 /* delay */, () -> {
306 view.setVisibility(endState);
307 if (callback != null) {
308 callback.run();
309 }
310 });
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +0900311 } else {
312 view.setVisibility(endState);
Peter Caia8178f52019-05-22 13:01:01 +0800313 if (callback != null) {
314 callback.run();
315 }
Tetsutoki Shiozawace9645b2018-09-05 13:17:01 +0900316 }
317 }
318
319 private void show(View view) {
320 if (mAnimationsEnabled) {
321 CrossFadeHelper.fadeIn(view, CONTENT_FADE_DURATION /* duration */,
322 CONTENT_FADE_DELAY /* delay */);
323 } else {
324 view.setVisibility(View.VISIBLE);
325 }
326 }
327
328 @VisibleForTesting
329 void setAnimationsEnabled(boolean enabled) {
330 mAnimationsEnabled = enabled;
331 }
332
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800333 @VisibleForTesting
334 public boolean isShown() {
335 return mShown;
336 }
337
Selim Cinek332c23f2018-03-16 17:37:50 -0700338 /**
339 * Should the headsup status bar view be visible right now? This may be different from isShown,
340 * since the headsUp manager might not have notified us yet of the state change.
341 *
342 * @return if the heads up status bar view should be shown
343 */
344 public boolean shouldBeVisible() {
345 return !mIsExpanded && mHeadsUpManager.hasPinnedHeadsUp();
346 }
347
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800348 @Override
Ned Burnsf81c4c42019-01-07 14:10:43 -0500349 public void onHeadsUpUnPinned(NotificationEntry entry) {
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800350 updateTopEntry();
Evan Laird94492852018-10-25 13:43:01 -0400351 updateHeader(entry);
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800352 }
353
354 public void setExpandedHeight(float expandedHeight, float appearFraction) {
355 boolean changedHeight = expandedHeight != mExpandedHeight;
356 mExpandedHeight = expandedHeight;
357 mExpandFraction = appearFraction;
358 boolean isExpanded = expandedHeight > 0;
359 if (changedHeight) {
360 updateHeadsUpHeaders();
361 }
362 if (isExpanded != mIsExpanded) {
363 mIsExpanded = isExpanded;
364 updateTopEntry();
365 }
366 }
367
368 /**
369 * Set a headsUp to be tracked, meaning that it is currently being pulled down after being
370 * in a pinned state on the top. The expand animation is different in that case and we need
371 * to update the header constantly afterwards.
372 *
373 * @param trackedChild the tracked headsUp or null if it's not tracking anymore.
374 */
375 public void setTrackingHeadsUp(ExpandableNotificationRow trackedChild) {
376 ExpandableNotificationRow previousTracked = mTrackedChild;
377 mTrackedChild = trackedChild;
378 if (previousTracked != null) {
379 updateHeader(previousTracked.getEntry());
380 }
381 }
382
383 private void updateHeadsUpHeaders() {
384 mHeadsUpManager.getAllEntries().forEach(entry -> {
385 updateHeader(entry);
386 });
387 }
388
Ned Burnsf81c4c42019-01-07 14:10:43 -0500389 public void updateHeader(NotificationEntry entry) {
Evan Laird94492852018-10-25 13:43:01 -0400390 ExpandableNotificationRow row = entry.getRow();
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800391 float headerVisibleAmount = 1.0f;
Selim Cinekf0c79e12018-05-14 17:17:31 -0700392 if (row.isPinned() || row.isHeadsUpAnimatingAway() || row == mTrackedChild) {
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800393 headerVisibleAmount = mExpandFraction;
394 }
395 row.setHeaderVisibleAmount(headerVisibleAmount);
396 }
397
398 @Override
399 public void onDarkChanged(Rect area, float darkIntensity, int tint) {
400 mHeadsUpStatusBarView.onDarkChanged(area, darkIntensity, tint);
401 }
402
403 public void setPublicMode(boolean publicMode) {
404 mHeadsUpStatusBarView.setPublicMode(publicMode);
405 updateTopEntry();
406 }
felkachange6c03a02018-05-24 15:38:04 +0800407
408 void readFrom(HeadsUpAppearanceController oldController) {
409 if (oldController != null) {
410 mTrackedChild = oldController.mTrackedChild;
411 mExpandedHeight = oldController.mExpandedHeight;
412 mIsExpanded = oldController.mIsExpanded;
413 mExpandFraction = oldController.mExpandFraction;
414 }
415 }
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800416}