diff options
-rw-r--r-- | core/java/android/widget/GridLayout.java | 120 | ||||
-rw-r--r-- | core/jni/android_view_InputEventReceiver.cpp | 2 | ||||
-rw-r--r-- | services/common_time/Android.mk | 2 | ||||
-rw-r--r-- | services/common_time/clock_recovery.cpp | 252 | ||||
-rw-r--r-- | services/common_time/clock_recovery.h | 77 | ||||
-rw-r--r-- | services/common_time/common_time_server.cpp | 2 | ||||
-rw-r--r-- | services/common_time/common_time_server.h | 1 | ||||
-rw-r--r-- | services/common_time/diag_thread.cpp | 14 | ||||
-rw-r--r-- | services/common_time/diag_thread.h | 8 | ||||
-rw-r--r-- | services/java/com/android/server/wm/WindowManagerService.java | 17 | ||||
-rwxr-xr-x | tools/aidl/Type.cpp | 4 | ||||
-rw-r--r-- | tools/aidl/generate_java_rpc.cpp | 16 |
12 files changed, 235 insertions, 280 deletions
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java index ea40dc2..fc08cc5 100644 --- a/core/java/android/widget/GridLayout.java +++ b/core/java/android/widget/GridLayout.java @@ -127,8 +127,7 @@ import static java.lang.Math.min; * * GridLayout does not provide support for the principle of <em>weight</em>, as defined in * {@link LinearLayout.LayoutParams#weight}. In general, it is not therefore possible - * to configure a GridLayout to distribute excess space in non-trivial proportions between - * multiple rows or columns. + * to configure a GridLayout to distribute excess space between multiple components. * <p> * Some common use-cases may nevertheless be accommodated as follows. * To place equal amounts of space around a component in a cell group; @@ -209,7 +208,6 @@ public class GridLayout extends ViewGroup { static final String TAG = GridLayout.class.getName(); static final boolean DEBUG = false; - static final int PRF = 1; static final int MAX_SIZE = 100000; static final int DEFAULT_CONTAINER_MARGIN = 0; static final int UNINITIALIZED_HASH = 0; @@ -779,7 +777,7 @@ public class GridLayout extends ViewGroup { } } - private void drawRect(Canvas canvas, int x1, int y1, int x2, int y2, Paint paint) { + private static void drawRect(Canvas canvas, int x1, int y1, int x2, int y2, Paint paint) { canvas.drawRect(x1, y1, x2 - 1, y2 - 1, paint); } @@ -957,10 +955,6 @@ public class GridLayout extends ViewGroup { resolveSizeAndState(measuredHeight, heightSpec, 0)); } - private int protect(int alignment) { - return (alignment == UNDEFINED) ? 0 : alignment; - } - private int getMeasurement(View c, boolean horizontal) { return horizontal ? c.getMeasuredWidth() : c.getMeasuredHeight(); } @@ -1040,42 +1034,31 @@ public class GridLayout extends ViewGroup { Alignment hAlign = getAlignment(columnSpec.alignment, true); Alignment vAlign = getAlignment(rowSpec.alignment, false); - Bounds colBounds = horizontalAxis.getGroupBounds().getValue(i); - Bounds rowBounds = verticalAxis.getGroupBounds().getValue(i); + Bounds boundsX = horizontalAxis.getGroupBounds().getValue(i); + Bounds boundsY = verticalAxis.getGroupBounds().getValue(i); // Gravity offsets: the location of the alignment group relative to its cell group. - //noinspection NullableProblems - int gravityOffsetX = protect(hAlign.getAlignmentValue(null, - cellWidth - colBounds.size(true))); - //noinspection NullableProblems - int gravityOffsetY = protect(vAlign.getAlignmentValue(null, - cellHeight - rowBounds.size(true))); - - boolean rtl = isLayoutRtl(); - int startMargin = getMargin(c, true, !rtl); + int gravityOffsetX = hAlign.getGravityOffset(c, cellWidth - boundsX.size(true)); + int gravityOffsetY = vAlign.getGravityOffset(c, cellHeight - boundsY.size(true)); + + int leftMargin = getMargin(c, true, true); int topMargin = getMargin(c, false, true); - int endMargin = getMargin(c, true, rtl); + int rightMargin = getMargin(c, true, false); int bottomMargin = getMargin(c, false, false); - // Same calculation as getMeasurementIncludingMargin() - int mWidth = startMargin + pWidth + endMargin; - int mHeight = topMargin + pHeight + bottomMargin; - // Alignment offsets: the location of the view relative to its alignment group. - int alignmentOffsetX = colBounds.getOffset(c, hAlign, mWidth); - int alignmentOffsetY = rowBounds.getOffset(c, vAlign, mHeight); + int alignmentOffsetX = boundsX.getOffset(c, hAlign, leftMargin + pWidth + rightMargin); + int alignmentOffsetY = boundsY.getOffset(c, vAlign, topMargin + pHeight + bottomMargin); - int dx = gravityOffsetX + alignmentOffsetX + startMargin; - int dy = gravityOffsetY + alignmentOffsetY + topMargin; + int width = hAlign.getSizeInCell(c, pWidth, cellWidth - leftMargin - rightMargin); + int height = vAlign.getSizeInCell(c, pHeight, cellHeight - topMargin - bottomMargin); - cellWidth -= startMargin + endMargin; - cellHeight -= topMargin + bottomMargin; + int dx = x1 + gravityOffsetX + alignmentOffsetX; - int width = hAlign.getSizeInCell(c, pWidth, cellWidth, PRF); - int height = vAlign.getSizeInCell(c, pHeight, cellHeight, PRF); + int cx = !isLayoutRtl() ? paddingLeft + leftMargin + dx : + targetWidth - width - paddingRight - rightMargin - dx; + int cy = paddingTop + y1 + gravityOffsetY + alignmentOffsetY + topMargin; - int cx = rtl ? targetWidth - paddingRight - x1 - dx - width : paddingLeft + x1 + dx; - int cy = paddingTop + y1 + dy; if (width != c.getMeasuredWidth() || height != c.getMeasuredHeight()) { c.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY)); } @@ -1694,7 +1677,7 @@ public class GridLayout extends ViewGroup { * each cell group. The fundamental parameters associated with each cell group are * gathered into their vertical and horizontal components and stored * in the {@link #rowSpec} and {@link #columnSpec} layout parameters. - * {@link android.widget.GridLayout.Spec Specs} are immutable structures + * {@link GridLayout.Spec Specs} are immutable structures * and may be shared between the layout parameters of different children. * <p> * The row and column specs contain the leading and trailing indices along each axis @@ -1747,7 +1730,7 @@ public class GridLayout extends ViewGroup { * <li>{@link #rowSpec}<code>.alignment</code> = {@link #BASELINE} </li> * <li>{@link #columnSpec}<code>.column</code> = {@link #UNDEFINED} </li> * <li>{@link #columnSpec}<code>.columnSpan</code> = 1 </li> - * <li>{@link #columnSpec}<code>.alignment</code> = {@link #LEFT} </li> + * <li>{@link #columnSpec}<code>.alignment</code> = {@link #START} </li> * </ul> * * See {@link GridLayout} for a more complete description of the conventions @@ -1936,7 +1919,7 @@ public class GridLayout extends ViewGroup { /** * Describes how the child views are positioned. Default is {@code LEFT | BASELINE}. - * See {@link android.view.Gravity}. + * See {@link Gravity}. * * @param gravity the new gravity value * @@ -2426,8 +2409,8 @@ public class GridLayout extends ViewGroup { * group is specified by the two alignments which act along each axis independently. * <p> * The GridLayout class defines the most common alignments used in general layout: - * {@link #TOP}, {@link #LEFT}, {@link #BOTTOM}, {@link #RIGHT}, {@link #CENTER}, {@link - * #BASELINE} and {@link #FILL}. + * {@link #TOP}, {@link #LEFT}, {@link #BOTTOM}, {@link #RIGHT}, {@link #START}, + * {@link #END}, {@link #CENTER}, {@link #BASELINE} and {@link #FILL}. */ /* * An Alignment implementation must define {@link #getAlignmentValue(View, int, int)}, @@ -2441,6 +2424,8 @@ public class GridLayout extends ViewGroup { Alignment() { } + abstract int getGravityOffset(View view, int cellDelta); + /** * Returns an alignment value. In the case of vertical alignments the value * returned should indicate the distance from the top of the view to the @@ -2463,12 +2448,9 @@ public class GridLayout extends ViewGroup { * @param view the view to which this alignment should be applied * @param viewSize the measured size of the view * @param cellSize the size of the cell into which this view will be placed - * @param measurementType This parameter is currently unused as GridLayout only supports - * one type of measurement: {@link View#measure(int, int)}. - * * @return the aligned size */ - int getSizeInCell(View view, int viewSize, int cellSize, int measurementType) { + int getSizeInCell(View view, int viewSize, int cellSize) { return viewSize; } @@ -2479,6 +2461,11 @@ public class GridLayout extends ViewGroup { static final Alignment UNDEFINED_ALIGNMENT = new Alignment() { @Override + int getGravityOffset(View view, int cellDelta) { + return UNDEFINED; + } + + @Override public int getAlignmentValue(View view, int viewSize) { return UNDEFINED; } @@ -2490,6 +2477,11 @@ public class GridLayout extends ViewGroup { */ private static final Alignment LEADING = new Alignment() { @Override + int getGravityOffset(View view, int cellDelta) { + return 0; + } + + @Override public int getAlignmentValue(View view, int viewSize) { return 0; } @@ -2501,6 +2493,11 @@ public class GridLayout extends ViewGroup { */ private static final Alignment TRAILING = new Alignment() { @Override + int getGravityOffset(View view, int cellDelta) { + return cellDelta; + } + + @Override public int getAlignmentValue(View view, int viewSize) { return viewSize; } @@ -2530,15 +2527,16 @@ public class GridLayout extends ViewGroup { */ public static final Alignment END = TRAILING; - private static Alignment getAbsoluteAlignment(final Alignment a1, final Alignment a2) { + private static Alignment createSwitchingAlignment(final Alignment ltr, final Alignment rtl) { return new Alignment() { @Override + int getGravityOffset(View view, int cellDelta) { + return (!view.isLayoutRtl() ? ltr : rtl).getGravityOffset(view, cellDelta); + } + + @Override public int getAlignmentValue(View view, int viewSize) { - if (view == null) { - return UNDEFINED; - } - Alignment alignment = view.isLayoutRtl() ? a2 : a1; - return alignment.getAlignmentValue(view, viewSize); + return (!view.isLayoutRtl() ? ltr : rtl).getAlignmentValue(view, viewSize); } }; } @@ -2547,13 +2545,13 @@ public class GridLayout extends ViewGroup { * Indicates that a view should be aligned with the <em>left</em> * edges of the other views in its cell group. */ - public static final Alignment LEFT = getAbsoluteAlignment(START, END); + public static final Alignment LEFT = createSwitchingAlignment(START, END); /** * Indicates that a view should be aligned with the <em>right</em> * edges of the other views in its cell group. */ - public static final Alignment RIGHT = getAbsoluteAlignment(END, START); + public static final Alignment RIGHT = createSwitchingAlignment(END, START); /** * Indicates that a view should be <em>centered</em> with the other views in its cell group. @@ -2562,6 +2560,11 @@ public class GridLayout extends ViewGroup { */ public static final Alignment CENTER = new Alignment() { @Override + int getGravityOffset(View view, int cellDelta) { + return cellDelta >> 1; + } + + @Override public int getAlignmentValue(View view, int viewSize) { return viewSize >> 1; } @@ -2576,10 +2579,12 @@ public class GridLayout extends ViewGroup { */ public static final Alignment BASELINE = new Alignment() { @Override + int getGravityOffset(View view, int cellDelta) { + return 0; // baseline gravity is top + } + + @Override public int getAlignmentValue(View view, int viewSize) { - if (view == null) { - return UNDEFINED; - } int baseline = view.getBaseline(); return (baseline == -1) ? UNDEFINED : baseline; } @@ -2627,12 +2632,17 @@ public class GridLayout extends ViewGroup { */ public static final Alignment FILL = new Alignment() { @Override + int getGravityOffset(View view, int cellDelta) { + return 0; + } + + @Override public int getAlignmentValue(View view, int viewSize) { return UNDEFINED; } @Override - public int getSizeInCell(View view, int viewSize, int cellSize, int measurementType) { + public int getSizeInCell(View view, int viewSize, int cellSize) { return cellSize; } }; diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index ee41398..9df280d 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -264,7 +264,7 @@ static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jint receiverPtr, sp<NativeInputEventReceiver> receiver = reinterpret_cast<NativeInputEventReceiver*>(receiverPtr); status_t status = receiver->finishInputEvent(seq, handled); - if (status) { + if (status && status != DEAD_OBJECT) { String8 message; message.appendFormat("Failed to finish input event. status=%d", status); jniThrowRuntimeException(env, message.string()); diff --git a/services/common_time/Android.mk b/services/common_time/Android.mk index aabe572..e534d49 100644 --- a/services/common_time/Android.mk +++ b/services/common_time/Android.mk @@ -16,6 +16,8 @@ LOCAL_SRC_FILES := \ common_clock.cpp \ main.cpp +# Uncomment to enable vesbose logging and debug service. +#TIME_SERVICE_DEBUG=true ifeq ($(TIME_SERVICE_DEBUG), true) LOCAL_SRC_FILES += diag_thread.cpp LOCAL_CFLAGS += -DTIME_SERVICE_DEBUG diff --git a/services/common_time/clock_recovery.cpp b/services/common_time/clock_recovery.cpp index be054fb..6c98d32 100644 --- a/services/common_time/clock_recovery.cpp +++ b/services/common_time/clock_recovery.cpp @@ -33,6 +33,14 @@ #include "diag_thread.h" #endif +// Define log macro so we can make LOGV into LOGE when we are exclusively +// debugging this code. +#ifdef TIME_SERVICE_DEBUG +#define LOG_TS ALOGE +#else +#define LOG_TS ALOGV +#endif + namespace android { ClockRecoveryLoop::ClockRecoveryLoop(LocalClock* local_clock, @@ -46,7 +54,6 @@ ClockRecoveryLoop::ClockRecoveryLoop(LocalClock* local_clock, local_clock_can_slew_ = local_clock_->initCheck() && (local_clock_->setLocalSlew(0) == OK); - computePIDParams(); reset(true, true); #ifdef TIME_SERVICE_DEBUG @@ -66,6 +73,19 @@ ClockRecoveryLoop::~ClockRecoveryLoop() { #endif } +// Constants. +const float ClockRecoveryLoop::dT = 1.0; +const float ClockRecoveryLoop::Kc = 1.0f; +const float ClockRecoveryLoop::Ti = 15.0f; +const float ClockRecoveryLoop::Tf = 0.05; +const float ClockRecoveryLoop::bias_Fc = 0.01; +const float ClockRecoveryLoop::bias_RC = (dT / (2 * 3.14159f * bias_Fc)); +const float ClockRecoveryLoop::bias_Alpha = (dT / (bias_RC + dT)); +const int64_t ClockRecoveryLoop::panic_thresh_ = 50000; +const int64_t ClockRecoveryLoop::control_thresh_ = 10000; +const float ClockRecoveryLoop::COmin = -100.0f; +const float ClockRecoveryLoop::COmax = 100.0f; + void ClockRecoveryLoop::reset(bool position, bool frequency) { Mutex::Autolock lock(&lock_); reset_l(position, frequency); @@ -86,6 +106,16 @@ bool ClockRecoveryLoop::pushDisciplineEvent(int64_t local_time, int64_t rtt) { Mutex::Autolock lock(&lock_); + int64_t local_common_time = 0; + common_clock_->localToCommon(local_time, &local_common_time); + int64_t raw_delta = nominal_common_time - local_common_time; + +#ifdef TIME_SERVICE_DEBUG + ALOGE("local=%lld, common=%lld, delta=%lld, rtt=%lld\n", + local_common_time, nominal_common_time, + raw_delta, rtt); +#endif + // If we have not defined a basis for common time, then we need to use these // initial points to do so. In order to avoid significant initial error // from a particularly bad startup data point, we collect the first N data @@ -113,11 +143,8 @@ bool ClockRecoveryLoop::pushDisciplineEvent(int64_t local_time, int64_t observed_common; int64_t delta; - int32_t delta32; + float delta_f, dCO; int32_t correction_cur; - int32_t correction_cur_P = 0; - int32_t correction_cur_I = 0; - int32_t correction_cur_D = 0; if (OK != common_clock_->localToCommon(local_time, &observed_common)) { // Since we just checked to make certain that this conversion was valid, @@ -165,72 +192,69 @@ bool ClockRecoveryLoop::pushDisciplineEvent(int64_t local_time, filter_data_[filter_wr_].nominal_common_time = nominal_common_time; filter_data_[filter_wr_].rtt = rtt; filter_data_[filter_wr_].point_used = false; + uint32_t current_point = filter_wr_; filter_wr_ = (filter_wr_ + 1) % kFilterSize; if (!filter_wr_) filter_full_ = true; - // Scan the accumulated data for the point with the minimum RTT. If that - // point has never been used before, go ahead and use it now, otherwise just - // do nothing. uint32_t scan_end = filter_full_ ? kFilterSize : filter_wr_; uint32_t min_rtt = findMinRTTNdx(filter_data_, scan_end); - if (filter_data_[min_rtt].point_used) - return true; + // We only use packets with low RTTs for control. If the packet RTT + // is less than the panic threshold, we can probably eat the jitter with the + // control loop. Otherwise, take the packet only if it better than all + // of the packets we have in the history. That way we try to track + // something, even if it is noisy. + if (current_point == min_rtt || rtt < control_thresh_) { + delta_f = delta = nominal_common_time - observed_common; + + // Compute the error then clamp to the panic threshold. If we ever + // exceed this amt of error, its time to panic and reset the system. + // Given that the error in the measurement of the error could be as + // high as the RTT of the data point, we don't actually panic until + // the implied error (delta) is greater than the absolute panic + // threashold plus the RTT. IOW - we don't panic until we are + // absoluely sure that our best case sync is worse than the absolute + // panic threshold. + int64_t effective_panic_thresh = panic_thresh_ + rtt; + if ((delta > effective_panic_thresh) || + (delta < -effective_panic_thresh)) { + // PANIC!!! + reset_l(false, true); + return false; + } - local_time = filter_data_[min_rtt].local_time; - observed_common = filter_data_[min_rtt].observed_common_time; - nominal_common_time = filter_data_[min_rtt].nominal_common_time; - filter_data_[min_rtt].point_used = true; - - // Compute the error then clamp to the panic threshold. If we ever exceed - // this amt of error, its time to panic and reset the system. Given that - // the error in the measurement of the error could be as high as the RTT of - // the data point, we don't actually panic until the implied error (delta) - // is greater than the absolute panic threashold plus the RTT. IOW - we - // don't panic until we are absoluely sure that our best case sync is worse - // than the absolute panic threshold. - int64_t effective_panic_thresh = panic_thresh_ + filter_data_[min_rtt].rtt; - delta = nominal_common_time - observed_common; - if ((delta > effective_panic_thresh) || (delta < -effective_panic_thresh)) { - // PANIC!!! - // - // TODO(johngro) : need to report this to the upper levels of - // code. - reset_l(false, true); - return false; - } else - delta32 = delta; - - // Accumulate error into the integrated error, then clamp. - integrated_error_ += delta32; - if (integrated_error_ > pid_params_.integrated_delta_max) - integrated_error_ = pid_params_.integrated_delta_max; - else if (integrated_error_ < pid_params_.integrated_delta_min) - integrated_error_ = pid_params_.integrated_delta_min; - - // Compute the difference in error between last time and this time, then - // update last_delta_ - int32_t input_D = last_delta_valid_ ? delta32 - last_delta_ : 0; - last_delta_valid_ = true; - last_delta_ = delta32; - - // Compute the various components of the correction value. - correction_cur_P = doGainScale(pid_params_.gain_P, delta32); - correction_cur_I = doGainScale(pid_params_.gain_I, integrated_error_); - - // TODO(johngro) : the differential portion of this code used to rely - // upon a completely homogeneous discipline frequency. Now that the - // discipline frequency may not be homogeneous, its probably important - // to divide by the amt of time between discipline events during the - // gain calculation. - correction_cur_D = doGainScale(pid_params_.gain_D, input_D); - - // Compute the final correction value and clamp. - correction_cur = correction_cur_P + correction_cur_I + correction_cur_D; - if (correction_cur < pid_params_.correction_min) - correction_cur = pid_params_.correction_min; - else if (correction_cur > pid_params_.correction_max) - correction_cur = pid_params_.correction_max; + } else { + // We do not have a good packet to look at, but we also do not want to + // free-run the clock at some crazy slew rate. So we guess the + // trajectory of the clock based on the last controller output and the + // estimated bias of our clock against the master. + // The net effect of this is that CO == CObias after some extended + // period of no feedback. + delta_f = last_delta_f_ - dT*(CO - CObias); + delta = delta_f; + } + + // Velocity form PI control equation. + dCO = Kc * (1.0f + dT/Ti) * delta_f - Kc * last_delta_f_; + CO += dCO * Tf; // Filter CO by applying gain <1 here. + + // Save error terms for later. + last_delta_f_ = delta_f; + last_delta_ = delta; + + // Clamp CO to +/- 100ppm. + if (CO < COmin) + CO = COmin; + else if (CO > COmax) + CO = COmax; + + // Update the controller bias. + CObias = bias_Alpha * CO + (1.0f - bias_Alpha) * lastCObias; + lastCObias = CObias; + + // Convert PPM to 16-bit int range. Add some guard band (-0.01) so we + // don't get fp weirdness. + correction_cur = CO * 327.66; // If there was a change in the amt of correction to use, update the // system. @@ -239,17 +263,7 @@ bool ClockRecoveryLoop::pushDisciplineEvent(int64_t local_time, applySlew(); } - ALOGV("rtt %lld observed %lld nominal %lld delta = %5lld " - "int = %7d correction %5d (P %5d, I %5d, D %5d)\n", - filter_data_[min_rtt].rtt, - observed_common, - nominal_common_time, - nominal_common_time - observed_common, - integrated_error_, - correction_cur, - correction_cur_P, - correction_cur_I, - correction_cur_D); + LOG_TS("clock_loop %lld %f %f %f %d\n", raw_delta, delta_f, CO, CObias, correction_cur); #ifdef TIME_SERVICE_DEBUG diag_thread_->pushDisciplineEvent( @@ -257,9 +271,7 @@ bool ClockRecoveryLoop::pushDisciplineEvent(int64_t local_time, observed_common, nominal_common_time, correction_cur, - correction_cur_P, - correction_cur_I, - correction_cur_D); + rtt); #endif return true; @@ -274,46 +286,6 @@ int32_t ClockRecoveryLoop::getLastErrorEstimate() { return ICommonClock::kErrorEstimateUnknown; } -void ClockRecoveryLoop::computePIDParams() { - // TODO(johngro) : add the ability to fetch parameters from the driver/board - // level in case they have a HW clock discipline solution with parameters - // tuned specifically for it. - - // Correction factor is limited to MIN/MAX_INT_16 - pid_params_.correction_min = -0x8000; - pid_params_.correction_max = 0x7FFF; - - // Default proportional gain to 2^15:1000. (max proportional drive at 1mSec - // of instantaneous error) - memset(&pid_params_.gain_P, 0, sizeof(pid_params_.gain_P)); - pid_params_.gain_P.a_to_b_numer = 0x8000; - pid_params_.gain_P.a_to_b_denom = 1000; - - // Set the integral gain to 2^15:5000 - memset(&pid_params_.gain_I, 0, sizeof(pid_params_.gain_I)); - pid_params_.gain_I.a_to_b_numer = 0x8000; - pid_params_.gain_I.a_to_b_denom = 5000; - - // Default controller is just a PI controller. Right now, the network based - // measurements of the error are way to noisy to feed into the differential - // component of a PID controller. Someday we might come back and add some - // filtering of the error channel, but until then leave the controller as a - // simple PI controller. - memset(&pid_params_.gain_D, 0, sizeof(pid_params_.gain_D)); - - // Don't let the integral component of the controller wind up to - // the point where it would want to drive the correction factor - // past saturation. - int64_t tmp; - pid_params_.gain_I.doReverseTransform(pid_params_.correction_min, &tmp); - pid_params_.integrated_delta_min = static_cast<int32_t>(tmp); - pid_params_.gain_I.doReverseTransform(pid_params_.correction_max, &tmp); - pid_params_.integrated_delta_max = static_cast<int32_t>(tmp); - - // By default, panic when are certain that the sync error is > 20mSec; - panic_thresh_ = 20000; -} - void ClockRecoveryLoop::reset_l(bool position, bool frequency) { assert(NULL != common_clock_); @@ -325,8 +297,10 @@ void ClockRecoveryLoop::reset_l(bool position, bool frequency) { if (frequency) { last_delta_valid_ = false; last_delta_ = 0; - integrated_error_ = 0; - correction_cur_ = 0; + last_delta_f_ = 0.0; + correction_cur_ = 0x0; + CO = 0.0f; + lastCObias = CObias = 0.0f; applySlew(); } @@ -334,47 +308,13 @@ void ClockRecoveryLoop::reset_l(bool position, bool frequency) { filter_full_ = false; } -int32_t ClockRecoveryLoop::doGainScale(const LinearTransform& gain, - int32_t val) { - if (!gain.a_to_b_numer || !gain.a_to_b_denom || !val) - return 0; - - int64_t tmp; - int64_t val64 = static_cast<int64_t>(val); - if (!gain.doForwardTransform(val64, &tmp)) { - ALOGW("Overflow/Underflow while scaling %d in %s", - val, __PRETTY_FUNCTION__); - return (val < 0) ? INT32_MIN : INT32_MAX; - } - - if (tmp > INT32_MAX) { - ALOGW("Overflow while scaling %d in %s", val, __PRETTY_FUNCTION__); - return INT32_MAX; - } - - if (tmp < INT32_MIN) { - ALOGW("Underflow while scaling %d in %s", val, __PRETTY_FUNCTION__); - return INT32_MIN; - } - - return static_cast<int32_t>(tmp); -} - void ClockRecoveryLoop::applySlew() { if (local_clock_can_slew_) { local_clock_->setLocalSlew(correction_cur_); } else { // The SW clock recovery implemented by the common clock class expects - // values expressed in PPM. Map the MIN/MAX_INT_16 drive range to +/- - // 100ppm. - int sw_correction; - sw_correction = correction_cur_ - pid_params_.correction_min; - sw_correction *= 200; - sw_correction /= (pid_params_.correction_max - - pid_params_.correction_min); - sw_correction -= 100; - - common_clock_->setSlew(local_clock_->getLocalTime(), sw_correction); + // values expressed in PPM. CO is in ppm. + common_clock_->setSlew(local_clock_->getLocalTime(), CO); } } diff --git a/services/common_time/clock_recovery.h b/services/common_time/clock_recovery.h index 5c35c38..b7362be 100644 --- a/services/common_time/clock_recovery.h +++ b/services/common_time/clock_recovery.h @@ -43,27 +43,38 @@ class ClockRecoveryLoop { int32_t getLastErrorEstimate(); private: - typedef struct { - // Limits for the correction factor supplied to set_counter_slew_rate. - // The controller will always clamp its output to the range expressed by - // correction_(min|max) - int32_t correction_min; - int32_t correction_max; - - // Limits for the internal integration accumulator in the PID - // controller. The value of the accumulator is scaled by gain_I to - // produce the integral component of the PID controller output. - // Platforms can use these limits to prevent windup in the system - // if/when the correction factor needs to be driven to saturation for - // extended periods of time. - int32_t integrated_delta_min; - int32_t integrated_delta_max; - - // Gain for the P, I and D components of the controller. - LinearTransform gain_P; - LinearTransform gain_I; - LinearTransform gain_D; - } PIDParams; + + // Tuned using the "Good Gain" method. + // See: + // http://techteach.no/publications/books/dynamics_and_control/tuning_pid_controller.pdf + + // Controller period (1Hz for now). + static const float dT; + + // Controller gain, positive and unitless. Larger values converge faster, + // but can cause instability. + static const float Kc; + + // Integral reset time. Smaller values cause loop to track faster, but can + // also cause instability. + static const float Ti; + + // Controller output filter time constant. Range (0-1). Smaller values make + // output smoother, but slow convergence. + static const float Tf; + + // Low-pass filter for bias tracker. + static const float bias_Fc; // HZ + static const float bias_RC; // Computed in constructor. + static const float bias_Alpha; // Computed inconstructor. + + // The maximum allowed error (as indicated by a pushDisciplineEvent) before + // we panic. + static const int64_t panic_thresh_; + + // The maximum allowed error rtt time for packets to be used for control + // feedback, unless the packet is the best in recent memory. + static const int64_t control_thresh_; typedef struct { int64_t local_time; @@ -75,9 +86,7 @@ class ClockRecoveryLoop { static uint32_t findMinRTTNdx(DisciplineDataPoint* data, uint32_t count); - void computePIDParams(); void reset_l(bool position, bool frequency); - static int32_t doGainScale(const LinearTransform& gain, int32_t val); void applySlew(); // The local clock HW abstraction we use as the basis for common time. @@ -89,22 +98,28 @@ class ClockRecoveryLoop { CommonClock* common_clock_; Mutex lock_; - // The parameters computed to be used for the PID Controller. - PIDParams pid_params_; - - // The maximum allowed error (as indicated by a pushDisciplineEvent) before - // we panic. - int32_t panic_thresh_; - // parameters maintained while running and reset during a reset // of the frequency correction. bool last_delta_valid_; int32_t last_delta_; + float last_delta_f_; int32_t integrated_error_; int32_t correction_cur_; + // Contoller Output. + float CO; + + // Bias tracking for trajectory estimation. + float CObias; + float lastCObias; + + // Controller output bounds. The controller will not try to + // slew faster that +/-100ppm offset from center per interation. + static const float COmin; + static const float COmax; + // State kept for filtering the discipline data. - static const uint32_t kFilterSize = 6; + static const uint32_t kFilterSize = 16; DisciplineDataPoint filter_data_[kFilterSize]; uint32_t filter_wr_; bool filter_full_; diff --git a/services/common_time/common_time_server.cpp b/services/common_time/common_time_server.cpp index 4fed0d0..ef7fa16 100644 --- a/services/common_time/common_time_server.cpp +++ b/services/common_time/common_time_server.cpp @@ -870,7 +870,7 @@ bool CommonTimeServer::handleSyncResponse( if (shouldPanicNotGettingGoodData()) return becomeInitial("RX panic, no good data"); } else { - result = mClockRecovery.pushDisciplineEvent(avgLocal, avgCommon, rtt); + result = mClockRecovery.pushDisciplineEvent(avgLocal, avgCommon, rttCommon); mClient_LastGoodSyncRX = clientRxLocalTime; if (result) { diff --git a/services/common_time/common_time_server.h b/services/common_time/common_time_server.h index 1b55202..a0f549f 100644 --- a/services/common_time/common_time_server.h +++ b/services/common_time/common_time_server.h @@ -328,4 +328,3 @@ class CommonTimeServer : public Thread { } // namespace android #endif // ANDROID_COMMON_TIME_SERVER_H - diff --git a/services/common_time/diag_thread.cpp b/services/common_time/diag_thread.cpp index c8e6053..4cb9551 100644 --- a/services/common_time/diag_thread.cpp +++ b/services/common_time/diag_thread.cpp @@ -176,9 +176,7 @@ void DiagThread::pushDisciplineEvent(int64_t observed_local_time, int64_t observed_common_time, int64_t nominal_common_time, int32_t total_correction, - int32_t P_correction, - int32_t I_correction, - int32_t D_correction) { + int32_t rtt) { Mutex::Autolock lock(&discipline_log_lock_); DisciplineEventRecord evt; @@ -193,9 +191,7 @@ void DiagThread::pushDisciplineEvent(int64_t observed_local_time, evt.observed_common_time = observed_common_time; evt.nominal_common_time = nominal_common_time; evt.total_correction = total_correction; - evt.P_correction = P_correction; - evt.I_correction = I_correction; - evt.D_correction = D_correction; + evt.rtt = rtt; discipline_log_.push_back(evt); while (discipline_log_.size() > kMaxDisciplineLogSize) @@ -299,7 +295,7 @@ bool DiagThread::threadLoop() { char buf[1024]; DisciplineEventRecord& e = *discipline_log_.begin(); snprintf(buf, sizeof(buf), - "D,%lld,%lld,%lld,%lld,%lld,%lld,%d,%d,%d,%d\n", + "D,%lld,%lld,%lld,%lld,%lld,%lld,%d,%d\n", e.event_id, e.action_local_time, e.action_common_time, @@ -307,9 +303,7 @@ bool DiagThread::threadLoop() { e.observed_common_time, e.nominal_common_time, e.total_correction, - e.P_correction, - e.I_correction, - e.D_correction); + e.rtt); buf[sizeof(buf) - 1] = 0; if (data_fd_ >= 0) diff --git a/services/common_time/diag_thread.h b/services/common_time/diag_thread.h index 6ebe829..c630e0d 100644 --- a/services/common_time/diag_thread.h +++ b/services/common_time/diag_thread.h @@ -38,9 +38,7 @@ class DiagThread : public Thread { int64_t observed_common_time, int64_t nominal_common_time, int32_t total_correction, - int32_t P_correction, - int32_t I_correction, - int32_t D_correction); + int32_t rtt); private: typedef struct { @@ -51,9 +49,7 @@ class DiagThread : public Thread { int64_t observed_common_time; int64_t nominal_common_time; int32_t total_correction; - int32_t P_correction; - int32_t I_correction; - int32_t D_correction; + int32_t rtt; } DisciplineEventRecord; bool openListenSocket(); diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 1c81bb1..80ef0e6 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -6377,7 +6377,7 @@ public class WindowManagerService extends IWindowManager.Stub INJECTION_TIMEOUT_MILLIS); Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result); + return reportInjectionResult(result, pid); } /** @@ -6407,7 +6407,7 @@ public class WindowManagerService extends IWindowManager.Stub INJECTION_TIMEOUT_MILLIS); Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result); + return reportInjectionResult(result, pid); } /** @@ -6437,7 +6437,7 @@ public class WindowManagerService extends IWindowManager.Stub INJECTION_TIMEOUT_MILLIS); Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result); + return reportInjectionResult(result, pid); } /** @@ -6458,24 +6458,23 @@ public class WindowManagerService extends IWindowManager.Stub INJECTION_TIMEOUT_MILLIS); Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result); + return reportInjectionResult(result, pid); } - private boolean reportInjectionResult(int result) { + private boolean reportInjectionResult(int result, int pid) { switch (result) { case InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED: - Slog.w(TAG, "Input event injection permission denied."); + Slog.w(TAG, "Input event injection from pid " + pid + " permission denied."); throw new SecurityException( "Injecting to another application requires INJECT_EVENTS permission"); case InputManager.INPUT_EVENT_INJECTION_SUCCEEDED: - //Slog.v(TAG, "Input event injection succeeded."); return true; case InputManager.INPUT_EVENT_INJECTION_TIMED_OUT: - Slog.w(TAG, "Input event injection timed out."); + Slog.w(TAG, "Input event injection from pid " + pid + " timed out."); return false; case InputManager.INPUT_EVENT_INJECTION_FAILED: default: - Slog.w(TAG, "Input event injection failed."); + Slog.w(TAG, "Input event injection from pid " + pid + " failed."); return false; } } diff --git a/tools/aidl/Type.cpp b/tools/aidl/Type.cpp index d572af6..42e1226 100755 --- a/tools/aidl/Type.cpp +++ b/tools/aidl/Type.cpp @@ -123,7 +123,7 @@ register_base_types() RPC_DATA_TYPE = new RpcDataType(); NAMES.Add(RPC_DATA_TYPE); - RPC_ERROR_TYPE = new UserDataType("android.support.place.rpc", "RpcError", + RPC_ERROR_TYPE = new UserDataType("com.android.athome.rpc", "RpcError", true, __FILE__, __LINE__); NAMES.Add(RPC_ERROR_TYPE); @@ -1234,7 +1234,7 @@ GenericListType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variabl // ================================================================ RpcDataType::RpcDataType() - :UserDataType("android.support.place.rpc", "RpcData", true, true, true) + :UserDataType("com.android.athome.rpc", "RpcData", true, true, true) { } diff --git a/tools/aidl/generate_java_rpc.cpp b/tools/aidl/generate_java_rpc.cpp index e5fa076..ecff3a1 100644 --- a/tools/aidl/generate_java_rpc.cpp +++ b/tools/aidl/generate_java_rpc.cpp @@ -7,26 +7,26 @@ Type* SERVICE_CONTEXT_TYPE = new Type("android.content", "Context", Type::BUILT_IN, false, false, false); -Type* PRESENTER_BASE_TYPE = new Type("android.support.place.connector", +Type* PRESENTER_BASE_TYPE = new Type("com.android.athome.connector", "EventListener", Type::BUILT_IN, false, false, false); -Type* PRESENTER_LISTENER_BASE_TYPE = new Type("android.support.place.connector", +Type* PRESENTER_LISTENER_BASE_TYPE = new Type("com.android.athome.connector", "EventListener.Listener", Type::BUILT_IN, false, false, false); -Type* RPC_BROKER_TYPE = new Type("android.support.place.connector", "Broker", +Type* RPC_BROKER_TYPE = new Type("com.android.athome.connector", "Broker", Type::BUILT_IN, false, false, false); Type* RPC_CONTAINER_TYPE = new Type("com.android.athome.connector", "ConnectorContainer", Type::BUILT_IN, false, false, false); Type* PLACE_INFO_TYPE = new Type("android.support.place.connector", "PlaceInfo", Type::BUILT_IN, false, false, false); // TODO: Just use Endpoint, so this works for all endpoints. -Type* RPC_CONNECTOR_TYPE = new Type("android.support.place.connector", "Connector", +Type* RPC_CONNECTOR_TYPE = new Type("com.android.athome.connector", "Connector", Type::BUILT_IN, false, false, false); -Type* RPC_ENDPOINT_INFO_TYPE = new UserDataType("android.support.place.rpc", +Type* RPC_ENDPOINT_INFO_TYPE = new UserDataType("com.android.athome.rpc", "EndpointInfo", true, __FILE__, __LINE__); -Type* RPC_RESULT_HANDLER_TYPE = new UserDataType("android.support.place.rpc", "RpcResultHandler", +Type* RPC_RESULT_HANDLER_TYPE = new UserDataType("com.android.athome.rpc", "RpcResultHandler", true, __FILE__, __LINE__); -Type* RPC_ERROR_LISTENER_TYPE = new Type("android.support.place.rpc", "RpcErrorHandler", +Type* RPC_ERROR_LISTENER_TYPE = new Type("com.android.athome.rpc", "RpcErrorHandler", Type::BUILT_IN, false, false, false); -Type* RPC_CONTEXT_TYPE = new UserDataType("android.support.place.rpc", "RpcContext", true, +Type* RPC_CONTEXT_TYPE = new UserDataType("com.android.athome.rpc", "RpcContext", true, __FILE__, __LINE__); static void generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, |