Loading packages/SystemUI/res/values/config.xml +17 −1 Original line number Original line Diff line number Diff line Loading @@ -224,9 +224,25 @@ <!-- Doze: duration to avoid false pickup gestures triggered by notification vibrations --> <!-- Doze: duration to avoid false pickup gestures triggered by notification vibrations --> <integer name="doze_pickup_vibration_threshold">2000</integer> <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> <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? --> <!-- Doze: pulse parameter - how long does it take to fade in? --> <integer name="doze_pulse_duration_in">900</integer> <integer name="doze_pulse_duration_in">900</integer> Loading packages/SystemUI/src/com/android/systemui/doze/DozeService.java +12 −6 Original line number Original line Diff line number Diff line Loading @@ -214,6 +214,10 @@ public class DozeService extends DreamService { } } private void requestPulse(final int reason) { private void requestPulse(final int reason) { requestPulse(reason, false /* performedProxCheck */); } private void requestPulse(final int reason, boolean performedProxCheck) { if (mHost != null && mDreaming && !mPulsing) { if (mHost != null && mDreaming && !mPulsing) { // Let the host know we want to pulse. Wait for it to be ready, then // 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. // turn the screen on. When finished, turn the screen off again. Loading @@ -226,10 +230,9 @@ public class DozeService extends DreamService { return; return; } } final long start = SystemClock.uptimeMillis(); final long start = SystemClock.uptimeMillis(); final boolean nonBlocking = reason == DozeLog.PULSE_REASON_SENSOR_PICKUP if (performedProxCheck) { && mDozeParameters.getPickupPerformsProxCheck(); // the caller already performed a successful proximity check; we'll only do one to if (nonBlocking) { // capture statistics, continue pulsing immediately. // proximity check is only done to capture statistics, continue pulsing continuePulsing(reason); continuePulsing(reason); } } // perform a proximity check // perform a proximity check Loading @@ -239,7 +242,7 @@ public class DozeService extends DreamService { final boolean isNear = result == RESULT_NEAR; final boolean isNear = result == RESULT_NEAR; final long end = SystemClock.uptimeMillis(); final long end = SystemClock.uptimeMillis(); DozeLog.traceProximityResult(mContext, isNear, end - start, reason); DozeLog.traceProximityResult(mContext, isNear, end - start, reason); if (nonBlocking) { if (performedProxCheck) { // we already continued // we already continued return; return; } } Loading Loading @@ -540,9 +543,12 @@ public class DozeService extends DreamService { mWakeLock.acquire(); mWakeLock.acquire(); try { try { if (DEBUG) Log.d(mTag, "onTrigger: " + triggerEventToString(event)); if (DEBUG) Log.d(mTag, "onTrigger: " + triggerEventToString(event)); boolean sensorPerformsProxCheck = false; if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) { if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) { int subType = (int) event.values[0]; int subType = (int) event.values[0]; MetricsLogger.action(mContext, MetricsEvent.ACTION_AMBIENT_GESTURE, subType); MetricsLogger.action(mContext, MetricsEvent.ACTION_AMBIENT_GESTURE, subType); sensorPerformsProxCheck = mDozeParameters.getPickupSubtypePerformsProxCheck( subType); } } if (mDebugVibrate) { if (mDebugVibrate) { final Vibrator v = (Vibrator) mContext.getSystemService( final Vibrator v = (Vibrator) mContext.getSystemService( Loading @@ -555,7 +561,7 @@ public class DozeService extends DreamService { } } mRegistered = false; mRegistered = false; requestPulse(mPulseReason); requestPulse(mPulseReason, sensorPerformsProxCheck); updateListener(); // reregister, this sensor only fires once updateListener(); // reregister, this sensor only fires once // reset the notification pulse schedule, but only if we think we were not triggered // reset the notification pulse schedule, but only if we think we were not triggered Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +112 −5 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.os.SystemProperties; import android.text.TextUtils; import android.text.TextUtils; import android.util.Log; import android.util.Log; import android.util.MathUtils; import android.util.MathUtils; import android.util.SparseBooleanArray; import com.android.systemui.R; import com.android.systemui.R; Loading @@ -39,6 +40,8 @@ public class DozeParameters { private static PulseSchedule sPulseSchedule; private static PulseSchedule sPulseSchedule; private static IntInOutMatcher sPickupSubtypePerformsProxMatcher; public DozeParameters(Context context) { public DozeParameters(Context context) { mContext = context; mContext = context; } } Loading @@ -61,7 +64,20 @@ public class DozeParameters { pw.print(" getPulseSchedule(): "); pw.println(getPulseSchedule()); pw.print(" getPulseSchedule(): "); pw.println(getPulseSchedule()); pw.print(" getPulseScheduleResets(): "); pw.println(getPulseScheduleResets()); pw.print(" getPulseScheduleResets(): "); pw.println(getPulseScheduleResets()); pw.print(" getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold()); 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() { public boolean getDisplayStateSupported() { Loading Loading @@ -106,10 +122,6 @@ public class DozeParameters { return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse); 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() { public boolean getPulseOnNotifications() { return getBoolean("doze.pulse.notifications", R.bool.doze_pulse_on_notifications); return getBoolean("doze.pulse.notifications", R.bool.doze_pulse_on_notifications); } } Loading Loading @@ -143,6 +155,101 @@ public class DozeParameters { return SystemProperties.get(propName, mContext.getString(resId)); 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 { public static class PulseSchedule { private static final Pattern PATTERN = Pattern.compile("(\\d+?)s", 0); private static final Pattern PATTERN = Pattern.compile("(\\d+?)s", 0); Loading packages/SystemUI/tests/src/com/android/systemui/phone/DozeParametersTests.java 0 → 100644 +166 −0 Original line number Original line 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 Loading
packages/SystemUI/res/values/config.xml +17 −1 Original line number Original line Diff line number Diff line Loading @@ -224,9 +224,25 @@ <!-- Doze: duration to avoid false pickup gestures triggered by notification vibrations --> <!-- Doze: duration to avoid false pickup gestures triggered by notification vibrations --> <integer name="doze_pickup_vibration_threshold">2000</integer> <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> <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? --> <!-- Doze: pulse parameter - how long does it take to fade in? --> <integer name="doze_pulse_duration_in">900</integer> <integer name="doze_pulse_duration_in">900</integer> Loading
packages/SystemUI/src/com/android/systemui/doze/DozeService.java +12 −6 Original line number Original line Diff line number Diff line Loading @@ -214,6 +214,10 @@ public class DozeService extends DreamService { } } private void requestPulse(final int reason) { private void requestPulse(final int reason) { requestPulse(reason, false /* performedProxCheck */); } private void requestPulse(final int reason, boolean performedProxCheck) { if (mHost != null && mDreaming && !mPulsing) { if (mHost != null && mDreaming && !mPulsing) { // Let the host know we want to pulse. Wait for it to be ready, then // 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. // turn the screen on. When finished, turn the screen off again. Loading @@ -226,10 +230,9 @@ public class DozeService extends DreamService { return; return; } } final long start = SystemClock.uptimeMillis(); final long start = SystemClock.uptimeMillis(); final boolean nonBlocking = reason == DozeLog.PULSE_REASON_SENSOR_PICKUP if (performedProxCheck) { && mDozeParameters.getPickupPerformsProxCheck(); // the caller already performed a successful proximity check; we'll only do one to if (nonBlocking) { // capture statistics, continue pulsing immediately. // proximity check is only done to capture statistics, continue pulsing continuePulsing(reason); continuePulsing(reason); } } // perform a proximity check // perform a proximity check Loading @@ -239,7 +242,7 @@ public class DozeService extends DreamService { final boolean isNear = result == RESULT_NEAR; final boolean isNear = result == RESULT_NEAR; final long end = SystemClock.uptimeMillis(); final long end = SystemClock.uptimeMillis(); DozeLog.traceProximityResult(mContext, isNear, end - start, reason); DozeLog.traceProximityResult(mContext, isNear, end - start, reason); if (nonBlocking) { if (performedProxCheck) { // we already continued // we already continued return; return; } } Loading Loading @@ -540,9 +543,12 @@ public class DozeService extends DreamService { mWakeLock.acquire(); mWakeLock.acquire(); try { try { if (DEBUG) Log.d(mTag, "onTrigger: " + triggerEventToString(event)); if (DEBUG) Log.d(mTag, "onTrigger: " + triggerEventToString(event)); boolean sensorPerformsProxCheck = false; if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) { if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) { int subType = (int) event.values[0]; int subType = (int) event.values[0]; MetricsLogger.action(mContext, MetricsEvent.ACTION_AMBIENT_GESTURE, subType); MetricsLogger.action(mContext, MetricsEvent.ACTION_AMBIENT_GESTURE, subType); sensorPerformsProxCheck = mDozeParameters.getPickupSubtypePerformsProxCheck( subType); } } if (mDebugVibrate) { if (mDebugVibrate) { final Vibrator v = (Vibrator) mContext.getSystemService( final Vibrator v = (Vibrator) mContext.getSystemService( Loading @@ -555,7 +561,7 @@ public class DozeService extends DreamService { } } mRegistered = false; mRegistered = false; requestPulse(mPulseReason); requestPulse(mPulseReason, sensorPerformsProxCheck); updateListener(); // reregister, this sensor only fires once updateListener(); // reregister, this sensor only fires once // reset the notification pulse schedule, but only if we think we were not triggered // reset the notification pulse schedule, but only if we think we were not triggered Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +112 −5 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.os.SystemProperties; import android.text.TextUtils; import android.text.TextUtils; import android.util.Log; import android.util.Log; import android.util.MathUtils; import android.util.MathUtils; import android.util.SparseBooleanArray; import com.android.systemui.R; import com.android.systemui.R; Loading @@ -39,6 +40,8 @@ public class DozeParameters { private static PulseSchedule sPulseSchedule; private static PulseSchedule sPulseSchedule; private static IntInOutMatcher sPickupSubtypePerformsProxMatcher; public DozeParameters(Context context) { public DozeParameters(Context context) { mContext = context; mContext = context; } } Loading @@ -61,7 +64,20 @@ public class DozeParameters { pw.print(" getPulseSchedule(): "); pw.println(getPulseSchedule()); pw.print(" getPulseSchedule(): "); pw.println(getPulseSchedule()); pw.print(" getPulseScheduleResets(): "); pw.println(getPulseScheduleResets()); pw.print(" getPulseScheduleResets(): "); pw.println(getPulseScheduleResets()); pw.print(" getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold()); 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() { public boolean getDisplayStateSupported() { Loading Loading @@ -106,10 +122,6 @@ public class DozeParameters { return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse); 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() { public boolean getPulseOnNotifications() { return getBoolean("doze.pulse.notifications", R.bool.doze_pulse_on_notifications); return getBoolean("doze.pulse.notifications", R.bool.doze_pulse_on_notifications); } } Loading Loading @@ -143,6 +155,101 @@ public class DozeParameters { return SystemProperties.get(propName, mContext.getString(resId)); 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 { public static class PulseSchedule { private static final Pattern PATTERN = Pattern.compile("(\\d+?)s", 0); private static final Pattern PATTERN = Pattern.compile("(\\d+?)s", 0); Loading
packages/SystemUI/tests/src/com/android/systemui/phone/DozeParametersTests.java 0 → 100644 +166 −0 Original line number Original line 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