Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e0cac111 authored by Adrian Roos's avatar Adrian Roos Committed by android-build-merger
Browse files

Merge \"Doze: Add config for fine grained proximity checks\" into nyc-mr1-dev

am: 4ba23f30

Change-Id: Ibd911a479877fe6e944fcd421807c052fa05df70
parents 8b942b24 4ba23f30
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -224,9 +224,25 @@
    <!-- Doze: duration to avoid false pickup gestures triggered by notification vibrations -->
    <integer name="doze_pickup_vibration_threshold">2000</integer>

    <!-- Doze: can we assume the pickup sensor includes a proximity check? -->
    <!-- Doze: can we assume the pickup sensor includes a proximity check?
         This is ignored if doze_pickup_subtype_performs_proximity_check is not empty.
         @deprecated: use doze_pickup_subtype_performs_proximity_check instead.-->
    <bool name="doze_pickup_performs_proximity_check">false</bool>

    <!-- Doze: a list of pickup sensor subtypes that perform a proximity check before they trigger.
               If not empty, either * or !* must appear to specify the default.
               If empty, falls back to doze_pickup_performs_proximity_check.

               Examples: 1,2,3,!* -> subtypes 1,2 and 3 perform the check, all others don't.
                         !1,!2,*  -> subtypes 1 and 2 don't perform the check, all others do.
                         !8,*     -> subtype 8 does not perform the check, all others do
                         1,1,*    -> illegal, every item may only appear once
                         1,!1,*   -> illegal, no contradictions allowed
                         1,2      -> illegal, need either * or !*
                         1,,4a3   -> illegal, no empty or non-numeric terms allowed
    -->
    <string name="doze_pickup_subtype_performs_proximity_check"></string>

    <!-- Doze: pulse parameter - how long does it take to fade in? -->
    <integer name="doze_pulse_duration_in">900</integer>

+12 −6
Original line number Diff line number Diff line
@@ -214,6 +214,10 @@ public class DozeService extends DreamService {
    }

    private void requestPulse(final int reason) {
        requestPulse(reason, false /* performedProxCheck */);
    }

    private void requestPulse(final int reason, boolean performedProxCheck) {
        if (mHost != null && mDreaming && !mPulsing) {
            // Let the host know we want to pulse.  Wait for it to be ready, then
            // turn the screen on.  When finished, turn the screen off again.
@@ -226,10 +230,9 @@ public class DozeService extends DreamService {
                return;
            }
            final long start = SystemClock.uptimeMillis();
            final boolean nonBlocking = reason == DozeLog.PULSE_REASON_SENSOR_PICKUP
                    && mDozeParameters.getPickupPerformsProxCheck();
            if (nonBlocking) {
                // proximity check is only done to capture statistics, continue pulsing
            if (performedProxCheck) {
                // the caller already performed a successful proximity check; we'll only do one to
                // capture statistics, continue pulsing immediately.
                continuePulsing(reason);
            }
            // perform a proximity check
@@ -239,7 +242,7 @@ public class DozeService extends DreamService {
                    final boolean isNear = result == RESULT_NEAR;
                    final long end = SystemClock.uptimeMillis();
                    DozeLog.traceProximityResult(mContext, isNear, end - start, reason);
                    if (nonBlocking) {
                    if (performedProxCheck) {
                        // we already continued
                        return;
                    }
@@ -540,9 +543,12 @@ public class DozeService extends DreamService {
            mWakeLock.acquire();
            try {
                if (DEBUG) Log.d(mTag, "onTrigger: " + triggerEventToString(event));
                boolean sensorPerformsProxCheck = false;
                if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
                    int subType = (int) event.values[0];
                    MetricsLogger.action(mContext, MetricsEvent.ACTION_AMBIENT_GESTURE, subType);
                    sensorPerformsProxCheck = mDozeParameters.getPickupSubtypePerformsProxCheck(
                            subType);
                }
                if (mDebugVibrate) {
                    final Vibrator v = (Vibrator) mContext.getSystemService(
@@ -555,7 +561,7 @@ public class DozeService extends DreamService {
                }

                mRegistered = false;
                requestPulse(mPulseReason);
                requestPulse(mPulseReason, sensorPerformsProxCheck);
                updateListener();  // reregister, this sensor only fires once

                // reset the notification pulse schedule, but only if we think we were not triggered
+112 −5
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;
import android.util.MathUtils;
import android.util.SparseBooleanArray;

import com.android.systemui.R;

@@ -39,6 +40,8 @@ public class DozeParameters {

    private static PulseSchedule sPulseSchedule;

    private static IntInOutMatcher sPickupSubtypePerformsProxMatcher;

    public DozeParameters(Context context) {
        mContext = context;
    }
@@ -61,7 +64,20 @@ public class DozeParameters {
        pw.print("    getPulseSchedule(): "); pw.println(getPulseSchedule());
        pw.print("    getPulseScheduleResets(): "); pw.println(getPulseScheduleResets());
        pw.print("    getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold());
        pw.print("    getPickupPerformsProxCheck(): "); pw.println(getPickupPerformsProxCheck());
        pw.print("    getPickupSubtypePerformsProxCheck(): ");pw.println(
                dumpPickupSubtypePerformsProxCheck());
    }

    private String dumpPickupSubtypePerformsProxCheck() {
        // Refresh sPickupSubtypePerformsProxMatcher
        getPickupSubtypePerformsProxCheck(0);

        if (sPickupSubtypePerformsProxMatcher == null) {
            return "fallback: " + mContext.getResources().getBoolean(
                    R.bool.doze_pickup_performs_proximity_check);
        } else {
            return "spec: " + sPickupSubtypePerformsProxMatcher.mSpec;
        }
    }

    public boolean getDisplayStateSupported() {
@@ -106,10 +122,6 @@ public class DozeParameters {
        return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse);
    }

    public boolean getPickupPerformsProxCheck() {
        return getBoolean("doze.pickup.proxcheck", R.bool.doze_pickup_performs_proximity_check);
    }

    public boolean getPulseOnNotifications() {
        return getBoolean("doze.pulse.notifications", R.bool.doze_pulse_on_notifications);
    }
@@ -143,6 +155,101 @@ public class DozeParameters {
        return SystemProperties.get(propName, mContext.getString(resId));
    }

    public boolean getPickupSubtypePerformsProxCheck(int subType) {
        String spec = getString("doze.pickup.proxcheck",
                R.string.doze_pickup_subtype_performs_proximity_check);

        if (TextUtils.isEmpty(spec)) {
            // Fall back to non-subtype based property.
            return mContext.getResources().getBoolean(R.bool.doze_pickup_performs_proximity_check);
        }

        if (sPickupSubtypePerformsProxMatcher == null
                || !TextUtils.equals(spec, sPickupSubtypePerformsProxMatcher.mSpec)) {
            sPickupSubtypePerformsProxMatcher = new IntInOutMatcher(spec);
        }

        return sPickupSubtypePerformsProxMatcher.isIn(subType);
    }


    /**
     * Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
     * listed, will not match numbers that are listed with a ! prefix, and will match / not match
     * unlisted numbers depending on whether * or !* is present.
     *
     * *  -> match any numbers that are not explicitly listed
     * !* -> don't match any numbers that are not explicitly listed
     * 2  -> match 2
     * !3 -> don't match 3
     *
     * It is illegal to specify:
     * - an empty spec
     * - a spec containing that are empty, or a lone !
     * - a spec for anything other than numbers or *
     * - multiple terms for the same number / multiple *s
     */
    public static class IntInOutMatcher {
        private static final String WILDCARD = "*";
        private static final char OUT_PREFIX = '!';

        private final SparseBooleanArray mIsIn;
        private final boolean mDefaultIsIn;
        final String mSpec;

        public IntInOutMatcher(String spec) {
            if (TextUtils.isEmpty(spec)) {
                throw new IllegalArgumentException("Spec must not be empty");
            }

            boolean defaultIsIn = false;
            boolean foundWildcard = false;

            mSpec = spec;
            mIsIn = new SparseBooleanArray();

            for (String itemPrefixed : spec.split(",", -1)) {
                if (itemPrefixed.length() == 0) {
                    throw new IllegalArgumentException(
                            "Illegal spec, must not have zero-length items: `" + spec + "`");
                }
                boolean isIn = itemPrefixed.charAt(0) != OUT_PREFIX;
                String item = isIn ? itemPrefixed : itemPrefixed.substring(1);

                if (itemPrefixed.length() == 0) {
                    throw new IllegalArgumentException(
                            "Illegal spec, must not have zero-length items: `" + spec + "`");
                }

                if (WILDCARD.equals(item)) {
                    if (foundWildcard) {
                        throw new IllegalArgumentException("Illegal spec, `" + WILDCARD +
                                "` must not appear multiple times in `" + spec + "`");
                    }
                    defaultIsIn = isIn;
                    foundWildcard = true;
                } else {
                    int key = Integer.parseInt(item);
                    if (mIsIn.indexOfKey(key) >= 0) {
                        throw new IllegalArgumentException("Illegal spec, `" + key +
                                "` must not appear multiple times in `" + spec + "`");
                    }
                    mIsIn.put(key, isIn);
                }
            }

            if (!foundWildcard) {
                throw new IllegalArgumentException("Illegal spec, must specify either * or !*");
            }

            mDefaultIsIn = defaultIsIn;
        }

        public boolean isIn(int value) {
            return (mIsIn.get(value, mDefaultIsIn));
        }
    }

    public static class PulseSchedule {
        private static final Pattern PATTERN = Pattern.compile("(\\d+?)s", 0);

+166 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.systemui.phone;

import com.android.systemui.statusbar.phone.DozeParameters.IntInOutMatcher;

import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;

@SmallTest
public class DozeParametersTests extends AndroidTestCase {

    public void test_inOutMatcher_defaultIn() {
        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("*");

        assertTrue(intInOutMatcher.isIn(1));
        assertTrue(intInOutMatcher.isIn(-1));
        assertTrue(intInOutMatcher.isIn(0));
    }

    public void test_inOutMatcher_defaultOut() {
        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("!*");

        assertFalse(intInOutMatcher.isIn(1));
        assertFalse(intInOutMatcher.isIn(-1));
        assertFalse(intInOutMatcher.isIn(0));
    }

    public void test_inOutMatcher_someIn() {
        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("1,2,3,!*");

        assertTrue(intInOutMatcher.isIn(1));
        assertTrue(intInOutMatcher.isIn(2));
        assertTrue(intInOutMatcher.isIn(3));

        assertFalse(intInOutMatcher.isIn(0));
        assertFalse(intInOutMatcher.isIn(4));
    }

    public void test_inOutMatcher_someOut() {
        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("!1,!2,!3,*");

        assertFalse(intInOutMatcher.isIn(1));
        assertFalse(intInOutMatcher.isIn(2));
        assertFalse(intInOutMatcher.isIn(3));

        assertTrue(intInOutMatcher.isIn(0));
        assertTrue(intInOutMatcher.isIn(4));
    }

    public void test_inOutMatcher_mixed() {
        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("!1,2,!3,*");

        assertFalse(intInOutMatcher.isIn(1));
        assertTrue(intInOutMatcher.isIn(2));
        assertFalse(intInOutMatcher.isIn(3));

        assertTrue(intInOutMatcher.isIn(0));
        assertTrue(intInOutMatcher.isIn(4));
    }

    public void test_inOutMatcher_failEmpty() {
        try {
            new IntInOutMatcher("");
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

    public void test_inOutMatcher_failNull() {
        try {
            new IntInOutMatcher(null);
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

    public void test_inOutMatcher_failEmptyClause() {
        try {
            new IntInOutMatcher("!1,*,");
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

    public void test_inOutMatcher_failDuplicate() {
        try {
            new IntInOutMatcher("!1,*,!1");
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

    public void test_inOutMatcher_failDuplicateDefault() {
        try {
            new IntInOutMatcher("!1,*,*");
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

    public void test_inOutMatcher_failMalformedNot() {
        try {
            new IntInOutMatcher("!,*");
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

    public void test_inOutMatcher_failText() {
        try {
            new IntInOutMatcher("!abc,*");
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

    public void test_inOutMatcher_failContradiction() {
        try {
            new IntInOutMatcher("1,!1,*");
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

    public void test_inOutMatcher_failContradictionDefault() {
        try {
            new IntInOutMatcher("1,*,!*");
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

    public void test_inOutMatcher_failMissingDefault() {
        try {
            new IntInOutMatcher("1");
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

}
 No newline at end of file