From 02c228814a92d4aa10eea0fd456ea77b18988a7a Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Fri, 19 Jul 2013 03:04:12 +0100 Subject: [PATCH 01/31] WiFi - Add IBSS supported method --- api/current.txt | 3 +++ services/java/com/android/server/WifiService.java | 15 +++++++++++++++ wifi/java/android/net/wifi/IWifiManager.aidl | 2 ++ wifi/java/android/net/wifi/WifiManager.java | 12 ++++++++++++ wifi/java/android/net/wifi/WifiNative.java | 12 ++++++++++++ 5 files changed, 44 insertions(+) diff --git a/api/current.txt b/api/current.txt index 3bd70b23ae9..d86304fb439 100644 --- a/api/current.txt +++ b/api/current.txt @@ -13369,6 +13369,8 @@ package android.net.wifi { field public java.util.BitSet allowedPairwiseCiphers; field public java.util.BitSet allowedProtocols; field public boolean hiddenSSID; + field public boolean isIBSS; + field public int frequency; field public int networkId; field public java.lang.String preSharedKey; field public int priority; @@ -13457,6 +13459,7 @@ package android.net.wifi { method public java.util.List getScanResults(); method public int getWifiState(); method public boolean isWifiEnabled(); + method public boolean isIbssSupported(); method public boolean pingSupplicant(); method public boolean reassociate(); method public boolean reconnect(); diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 3a7392528a4..7b3898497b3 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -963,6 +963,21 @@ public List getSupportedChannels() { } } + /** + * Is Ad-Hoc (IBSS) mode supported by the driver? + * Will only return correct results when we have reached WIFI_STATE_ENABLED + * @return {@code true} if IBSS mode is supported, {@code false} if not + */ + public boolean isIbssSupported() { + enforceAccessPermission(); + if (mWifiStateMachineChannel != null) { + return (mWifiStateMachine.syncIsIbssSupported(mWifiStateMachineChannel) == 1); + } else { + Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); + return false; + } + } + /** * Return the DHCP-assigned addresses from the last successful DHCP request, * if any. diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index e53d6ac879c..1972965e4a5 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -74,6 +74,8 @@ interface IWifiManager List getSupportedChannels(); + boolean isIbssSupported(); + boolean saveConfiguration(); DhcpInfo getDhcpInfo(); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 12701fad144..2b7462f175a 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -896,6 +896,18 @@ public List getSupportedChannels() { } } + /** + * Check if the chipset supports IBSS (Adhoc) mode + * @return {@code true} if supported, {@code false} otherwise. + */ + public boolean isIbssSupported() { + try { + return mService.isIbssSupported(); + } catch (RemoteException e) { + return false; + } + } + /** * Return the DHCP-assigned addresses from the last successful DHCP request, * if any. diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index 43e3d3300d7..dfd4b85edc8 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -841,5 +841,17 @@ public List getSupportedChannels() { return channels; } + public boolean getModeCapability(String mode) { + String ret = doStringCommand("GET_CAPABILITY modes"); + if (!TextUtils.isEmpty(ret)) { + String[] tokens = ret.split(" "); + for (String t : tokens) { + if (t.compareTo(mode) == 0) + return true; + } + } + return false; + } + public native static boolean setMode(int mode); } From 9002dc565fe25d6970f6a365c29ce3c6f7ed94a3 Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Fri, 19 Jul 2013 03:06:31 +0100 Subject: [PATCH 02/31] WiFi - Get the list of supported channels --- .../src/com/android/rs/test/math.rs.orig | 436 ------------------ wifi/java/android/net/wifi/WifiManager.java | 13 + wifi/java/android/net/wifi/WifiNative.java | 30 ++ 3 files changed, 43 insertions(+), 436 deletions(-) delete mode 100644 tests/RenderScriptTests/tests_v14/src/com/android/rs/test/math.rs.orig diff --git a/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/math.rs.orig b/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/math.rs.orig deleted file mode 100644 index aae29a4c7e2..00000000000 --- a/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/math.rs.orig +++ /dev/null @@ -1,436 +0,0 @@ -#include "shared.rsh" - -// Testing math library - -volatile float f1; -volatile float2 f2; -volatile float3 f3; -volatile float4 f4; - -volatile int i1; -volatile int2 i2; -volatile int3 i3; -volatile int4 i4; - -volatile uint ui1; -volatile uint2 ui2; -volatile uint3 ui3; -volatile uint4 ui4; - -volatile short s1; -volatile short2 s2; -volatile short3 s3; -volatile short4 s4; - -volatile ushort us1; -volatile ushort2 us2; -volatile ushort3 us3; -volatile ushort4 us4; - -volatile char c1; -volatile char2 c2; -volatile char3 c3; -volatile char4 c4; - -volatile uchar uc1; -volatile uchar2 uc2; -volatile uchar3 uc3; -volatile uchar4 uc4; - -#define DECL_INT(prefix) \ -volatile char prefix##_c_1 = 1; \ -volatile char2 prefix##_c_2 = 1; \ -volatile char3 prefix##_c_3 = 1; \ -volatile char4 prefix##_c_4 = 1; \ -volatile uchar prefix##_uc_1 = 1; \ -volatile uchar2 prefix##_uc_2 = 1; \ -volatile uchar3 prefix##_uc_3 = 1; \ -volatile uchar4 prefix##_uc_4 = 1; \ -volatile short prefix##_s_1 = 1; \ -volatile short2 prefix##_s_2 = 1; \ -volatile short3 prefix##_s_3 = 1; \ -volatile short4 prefix##_s_4 = 1; \ -volatile ushort prefix##_us_1 = 1; \ -volatile ushort2 prefix##_us_2 = 1; \ -volatile ushort3 prefix##_us_3 = 1; \ -volatile ushort4 prefix##_us_4 = 1; \ -volatile int prefix##_i_1 = 1; \ -volatile int2 prefix##_i_2 = 1; \ -volatile int3 prefix##_i_3 = 1; \ -volatile int4 prefix##_i_4 = 1; \ -volatile uint prefix##_ui_1 = 1; \ -volatile uint2 prefix##_ui_2 = 1; \ -volatile uint3 prefix##_ui_3 = 1; \ -volatile uint4 prefix##_ui_4 = 1; \ -volatile long prefix##_l_1 = 1; \ -volatile ulong prefix##_ul_1 = 1; - -DECL_INT(res) -DECL_INT(src1) -DECL_INT(src2) - -#define TEST_INT_OP_TYPE(op, type) \ -rsDebug("Testing " #op " for " #type "1", i++); \ -res_##type##_1 = src1_##type##_1 op src2_##type##_1; \ -rsDebug("Testing " #op " for " #type "2", i++); \ -res_##type##_2 = src1_##type##_2 op src2_##type##_2; \ -rsDebug("Testing " #op " for " #type "3", i++); \ -res_##type##_3 = src1_##type##_3 op src2_##type##_3; \ -rsDebug("Testing " #op " for " #type "4", i++); \ -res_##type##_4 = src1_##type##_4 op src2_##type##_4; - -#define TEST_INT_OP(op) \ -TEST_INT_OP_TYPE(op, c) \ -TEST_INT_OP_TYPE(op, uc) \ -TEST_INT_OP_TYPE(op, s) \ -TEST_INT_OP_TYPE(op, us) \ -TEST_INT_OP_TYPE(op, i) \ -TEST_INT_OP_TYPE(op, ui) \ -rsDebug("Testing " #op " for l1", i++); \ -res_l_1 = src1_l_1 op src2_l_1; \ -rsDebug("Testing " #op " for ul1", i++); \ -res_ul_1 = src1_ul_1 op src2_ul_1; - -#define TEST_XN_FUNC_YN(typeout, fnc, typein) \ - res_##typeout##_1 = fnc(src1_##typein##_1); \ - res_##typeout##_2 = fnc(src1_##typein##_2); \ - res_##typeout##_3 = fnc(src1_##typein##_3); \ - res_##typeout##_4 = fnc(src1_##typein##_4); - -#define TEST_XN_FUNC_XN_XN(type, fnc) \ - res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1); \ - res_##type##_2 = fnc(src1_##type##_2, src2_##type##_2); \ - res_##type##_3 = fnc(src1_##type##_3, src2_##type##_3); \ - res_##type##_4 = fnc(src1_##type##_4, src2_##type##_4); - -#define TEST_X_FUNC_X_X_X(type, fnc) \ - res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1, src2_##type##_1); - -#define TEST_IN_FUNC_IN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - TEST_XN_FUNC_YN(uc, fnc, uc) \ - TEST_XN_FUNC_YN(c, fnc, c) \ - TEST_XN_FUNC_YN(us, fnc, us) \ - TEST_XN_FUNC_YN(s, fnc, s) \ - TEST_XN_FUNC_YN(ui, fnc, ui) \ - TEST_XN_FUNC_YN(i, fnc, i) - -#define TEST_UIN_FUNC_IN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - TEST_XN_FUNC_YN(uc, fnc, c) \ - TEST_XN_FUNC_YN(us, fnc, s) \ - TEST_XN_FUNC_YN(ui, fnc, i) \ - -#define TEST_IN_FUNC_IN_IN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - TEST_XN_FUNC_XN_XN(uc, fnc) \ - TEST_XN_FUNC_XN_XN(c, fnc) \ - TEST_XN_FUNC_XN_XN(us, fnc) \ - TEST_XN_FUNC_XN_XN(s, fnc) \ - TEST_XN_FUNC_XN_XN(ui, fnc) \ - TEST_XN_FUNC_XN_XN(i, fnc) - -#define TEST_I_FUNC_I_I_I(fnc) \ - rsDebug("Testing " #fnc, 0); \ - TEST_X_FUNC_X_X_X(uc, fnc) \ - TEST_X_FUNC_X_X_X(c, fnc) \ - TEST_X_FUNC_X_X_X(us, fnc) \ - TEST_X_FUNC_X_X_X(s, fnc) \ - TEST_X_FUNC_X_X_X(ui, fnc) \ - TEST_X_FUNC_X_X_X(i, fnc) - -#define TEST_FN_FUNC_FN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f1 = fnc(f1); \ - f2 = fnc(f2); \ - f3 = fnc(f3); \ - f4 = fnc(f4); - -#define TEST_FN_FUNC_FN_PFN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f1 = fnc(f1, (float*) &f1); \ - f2 = fnc(f2, (float2*) &f2); \ - f3 = fnc(f3, (float3*) &f3); \ - f4 = fnc(f4, (float4*) &f4); - -#define TEST_FN_FUNC_FN_FN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f1 = fnc(f1, f1); \ - f2 = fnc(f2, f2); \ - f3 = fnc(f3, f3); \ - f4 = fnc(f4, f4); - -#define TEST_F34_FUNC_F34_F34(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f3 = fnc(f3, f3); \ - f4 = fnc(f4, f4); - -#define TEST_FN_FUNC_FN_F(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f1 = fnc(f1, f1); \ - f2 = fnc(f2, f1); \ - f3 = fnc(f3, f1); \ - f4 = fnc(f4, f1); - -#define TEST_F_FUNC_FN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f1 = fnc(f1); \ - f1 = fnc(f2); \ - f1 = fnc(f3); \ - f1 = fnc(f4); - -#define TEST_F_FUNC_FN_FN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f1 = fnc(f1, f1); \ - f1 = fnc(f2, f2); \ - f1 = fnc(f3, f3); \ - f1 = fnc(f4, f4); - -#define TEST_FN_FUNC_FN_IN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f1 = fnc(f1, i1); \ - f2 = fnc(f2, i2); \ - f3 = fnc(f3, i3); \ - f4 = fnc(f4, i4); - -#define TEST_FN_FUNC_FN_I(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f1 = fnc(f1, i1); \ - f2 = fnc(f2, i1); \ - f3 = fnc(f3, i1); \ - f4 = fnc(f4, i1); - -#define TEST_FN_FUNC_FN_FN_FN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f1 = fnc(f1, f1, f1); \ - f2 = fnc(f2, f2, f2); \ - f3 = fnc(f3, f3, f3); \ - f4 = fnc(f4, f4, f4); - -#define TEST_FN_FUNC_FN_FN_F(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f1 = fnc(f1, f1, f1); \ - f2 = fnc(f2, f1, f1); \ - f3 = fnc(f3, f1, f1); \ - f4 = fnc(f4, f1, f1); - -#define TEST_FN_FUNC_FN_PIN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f1 = fnc(f1, (int*) &i1); \ - f2 = fnc(f2, (int2*) &i2); \ - f3 = fnc(f3, (int3*) &i3); \ - f4 = fnc(f4, (int4*) &i4); - -#define TEST_FN_FUNC_FN_FN_PIN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - f1 = fnc(f1, f1, (int*) &i1); \ - f2 = fnc(f2, f2, (int2*) &i2); \ - f3 = fnc(f3, f3, (int3*) &i3); \ - f4 = fnc(f4, f4, (int4*) &i4); - -#define TEST_IN_FUNC_FN(fnc) \ - rsDebug("Testing " #fnc, 0); \ - i1 = fnc(f1); \ - i2 = fnc(f2); \ - i3 = fnc(f3); \ - i4 = fnc(f4); - -static bool test_fp_math(uint32_t index) { - bool failed = false; - start(); - - TEST_FN_FUNC_FN(acos); - TEST_FN_FUNC_FN(acosh); - TEST_FN_FUNC_FN(acospi); - TEST_FN_FUNC_FN(asin); - TEST_FN_FUNC_FN(asinh); - TEST_FN_FUNC_FN(asinpi); - TEST_FN_FUNC_FN(atan); - TEST_FN_FUNC_FN_FN(atan2); - TEST_FN_FUNC_FN(atanh); - TEST_FN_FUNC_FN(atanpi); - TEST_FN_FUNC_FN_FN(atan2pi); - TEST_FN_FUNC_FN(cbrt); - TEST_FN_FUNC_FN(ceil); - TEST_FN_FUNC_FN_FN_FN(clamp); - TEST_FN_FUNC_FN_FN_F(clamp); - TEST_FN_FUNC_FN_FN(copysign); - TEST_FN_FUNC_FN(cos); - TEST_FN_FUNC_FN(cosh); - TEST_FN_FUNC_FN(cospi); - TEST_F34_FUNC_F34_F34(cross); - TEST_FN_FUNC_FN(degrees); - TEST_F_FUNC_FN_FN(distance); - TEST_F_FUNC_FN_FN(dot); - TEST_FN_FUNC_FN(erfc); - TEST_FN_FUNC_FN(erf); - TEST_FN_FUNC_FN(exp); - TEST_FN_FUNC_FN(exp2); - TEST_FN_FUNC_FN(exp10); - TEST_FN_FUNC_FN(expm1); - TEST_FN_FUNC_FN(fabs); - TEST_FN_FUNC_FN_FN(fdim); - TEST_FN_FUNC_FN(floor); - TEST_FN_FUNC_FN_FN_FN(fma); - TEST_FN_FUNC_FN_FN(fmax); - TEST_FN_FUNC_FN_F(fmax); - TEST_FN_FUNC_FN_FN(fmin); - TEST_FN_FUNC_FN_F(fmin); - TEST_FN_FUNC_FN_FN(fmod); - TEST_FN_FUNC_FN_PFN(fract); - TEST_FN_FUNC_FN_PIN(frexp); - TEST_FN_FUNC_FN_FN(hypot); - TEST_IN_FUNC_FN(ilogb); - TEST_FN_FUNC_FN_IN(ldexp); - TEST_FN_FUNC_FN_I(ldexp); - TEST_F_FUNC_FN(length); - TEST_FN_FUNC_FN(lgamma); - TEST_FN_FUNC_FN_PIN(lgamma); - TEST_FN_FUNC_FN(log); - TEST_FN_FUNC_FN(log2); - TEST_FN_FUNC_FN(log10); - TEST_FN_FUNC_FN(log1p); - TEST_FN_FUNC_FN(logb); - TEST_FN_FUNC_FN_FN_FN(mad); - TEST_FN_FUNC_FN_FN(max); - TEST_FN_FUNC_FN_F(max); - TEST_FN_FUNC_FN_FN(min); - TEST_FN_FUNC_FN_F(min); - TEST_FN_FUNC_FN_FN_FN(mix); - TEST_FN_FUNC_FN_FN_F(mix); - TEST_FN_FUNC_FN_PFN(modf); - // nan - TEST_FN_FUNC_FN_FN(nextafter); - TEST_FN_FUNC_FN(normalize); - TEST_FN_FUNC_FN_FN(pow); - TEST_FN_FUNC_FN_IN(pown); - TEST_FN_FUNC_FN_FN(powr); - TEST_FN_FUNC_FN(radians); - TEST_FN_FUNC_FN_FN(remainder); - TEST_FN_FUNC_FN_FN_PIN(remquo); - TEST_FN_FUNC_FN(rint); - TEST_FN_FUNC_FN_IN(rootn); - TEST_FN_FUNC_FN(round); - TEST_FN_FUNC_FN(rsqrt); - TEST_FN_FUNC_FN(sign); - TEST_FN_FUNC_FN(sin); - TEST_FN_FUNC_FN_PFN(sincos); - TEST_FN_FUNC_FN(sinh); - TEST_FN_FUNC_FN(sinpi); - TEST_FN_FUNC_FN(sqrt); - TEST_FN_FUNC_FN_FN(step); - TEST_FN_FUNC_FN_F(step); - TEST_FN_FUNC_FN(tan); - TEST_FN_FUNC_FN(tanh); - TEST_FN_FUNC_FN(tanpi); - TEST_FN_FUNC_FN(tgamma); - TEST_FN_FUNC_FN(trunc); - - float time = end(index); - - if (failed) { - rsDebug("test_fp_math FAILED", time); - } - else { - rsDebug("test_fp_math PASSED", time); - } - - return failed; -} - -static bool test_int_math(uint32_t index) { - bool failed = false; - start(); - - TEST_UIN_FUNC_IN(abs); - TEST_IN_FUNC_IN(clz); - TEST_IN_FUNC_IN_IN(min); - TEST_IN_FUNC_IN_IN(max); - TEST_I_FUNC_I_I_I(rsClamp); - - float time = end(index); - - if (failed) { - rsDebug("test_int_math FAILED", time); - } - else { - rsDebug("test_int_math PASSED", time); - } - - return failed; -} - -static bool test_basic_operators() { - bool failed = false; - int i = 0; - - TEST_INT_OP(+); - TEST_INT_OP(-); - TEST_INT_OP(*); - TEST_INT_OP(/); - TEST_INT_OP(%); - TEST_INT_OP(<<); - TEST_INT_OP(>>); - - if (failed) { - rsDebug("test_basic_operators FAILED", 0); - } - else { - rsDebug("test_basic_operators PASSED", 0); - } - - return failed; -} - -#define TEST_CVT(to, from, type) \ -rsDebug("Testing convert from " #from " to " #to, 0); \ -to##1 = from##1; \ -to##2 = convert_##type##2(from##2); \ -to##3 = convert_##type##3(from##3); \ -to##4 = convert_##type##4(from##4); - -#define TEST_CVT_MATRIX(to, type) \ -TEST_CVT(to, c, type); \ -TEST_CVT(to, uc, type); \ -TEST_CVT(to, s, type); \ -TEST_CVT(to, us, type); \ -TEST_CVT(to, i, type); \ -TEST_CVT(to, ui, type); \ -TEST_CVT(to, f, type); \ - -static bool test_convert() { - bool failed = false; - - TEST_CVT_MATRIX(c, char); - TEST_CVT_MATRIX(uc, uchar); - TEST_CVT_MATRIX(s, short); - TEST_CVT_MATRIX(us, ushort); - TEST_CVT_MATRIX(i, int); - TEST_CVT_MATRIX(ui, uint); - TEST_CVT_MATRIX(f, float); - - if (failed) { - rsDebug("test_convert FAILED", 0); - } - else { - rsDebug("test_convert PASSED", 0); - } - - return failed; -} - -void math_test(uint32_t index, int test_num) { - bool failed = false; - failed |= test_convert(); - failed |= test_fp_math(index); - failed |= test_int_math(index); - failed |= test_basic_operators(); - - if (failed) { - rsSendToClientBlocking(RS_MSG_TEST_FAILED); - } - else { - rsSendToClientBlocking(RS_MSG_TEST_PASSED); - } -} - diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 2b7462f175a..7e94ac7acdd 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -908,6 +908,19 @@ public boolean isIbssSupported() { } } + /** + * Get a list of supported channels / frequencies + * @return a List of WifiChannels + * @hide + */ + public List getSupportedChannels() { + try { + return mService.getSupportedChannels(); + } catch (RemoteException e) { + return null; + } + } + /** * Return the DHCP-assigned addresses from the last successful DHCP request, * if any. diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index dfd4b85edc8..0e22df683ec 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -853,5 +853,35 @@ public boolean getModeCapability(String mode) { return false; } + public List getSupportedChannels() { + boolean ibssAllowed; + List channels = new ArrayList(); + String ret = doStringCommand("GET_CAPABILITY channels"); + + if (!TextUtils.isEmpty(ret)) { + String[] lines = ret.split("\n"); + for (String l : lines) { + if (l.startsWith("Mode") || TextUtils.isEmpty(l)) continue; + + String[] tokens = l.split(" "); + if (tokens.length < 4) continue; + + if (tokens.length == 6 && tokens[5].contains("NO_IBSS")) + ibssAllowed = false; + else + ibssAllowed = true; + + try { + WifiChannel ch = new WifiChannel(Integer.parseInt(tokens[1]), Integer.parseInt(tokens[3]), ibssAllowed); + if (!channels.contains(ch)) + channels.add(ch); + } catch (java.lang.NumberFormatException e) { + Log.d(mTAG, "Can't parse: " + l); + } + } + } + return channels; + } + public native static boolean setMode(int mode); } From 56cf66591345867357672ab812e7c776bb252f7b Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Fri, 19 Jul 2013 21:34:08 +0100 Subject: [PATCH 03/31] remove duplicate entries --- wifi/java/android/net/wifi/IWifiManager.aidl | 2 -- 1 file changed, 2 deletions(-) diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 1972965e4a5..f834c70c8cf 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -70,8 +70,6 @@ interface IWifiManager boolean isDualBandSupported(); - boolean isIbssSupported(); - List getSupportedChannels(); boolean isIbssSupported(); From 6ef914800d161f7b5ab3114a36a6cddd526e9d85 Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Sat, 20 Jul 2013 11:50:25 +0100 Subject: [PATCH 04/31] fix duplicate entries --- wifi/java/android/net/wifi/WifiManager.java | 40 --------------------- 1 file changed, 40 deletions(-) diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 7e94ac7acdd..d62e3d2e28b 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -840,22 +840,6 @@ public void setFrequencyBand(int band, boolean persist) { } catch (RemoteException e) { } } - /** - * Get the operational frequency band. - * @return One of - * {@link #WIFI_FREQUENCY_BAND_AUTO}, - * {@link #WIFI_FREQUENCY_BAND_5GHZ}, - * {@link #WIFI_FREQUENCY_BAND_2GHZ} or - * {@code -1} on failure. - * @hide - */ - public int getFrequencyBand() { - try { - return mService.getFrequencyBand(); - } catch (RemoteException e) { - return -1; - } - } /** * Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz) @@ -896,30 +880,6 @@ public List getSupportedChannels() { } } - /** - * Check if the chipset supports IBSS (Adhoc) mode - * @return {@code true} if supported, {@code false} otherwise. - */ - public boolean isIbssSupported() { - try { - return mService.isIbssSupported(); - } catch (RemoteException e) { - return false; - } - } - - /** - * Get a list of supported channels / frequencies - * @return a List of WifiChannels - * @hide - */ - public List getSupportedChannels() { - try { - return mService.getSupportedChannels(); - } catch (RemoteException e) { - return null; - } - } /** * Return the DHCP-assigned addresses from the last successful DHCP request, From 6057a253068dce9014ae47b7f124701299a7b4fb Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Sat, 20 Jul 2013 12:20:56 +0100 Subject: [PATCH 05/31] remove some more duplicate entries --- wifi/java/android/net/wifi/WifiNative.java | 42 ---------------------- 1 file changed, 42 deletions(-) diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index 0e22df683ec..43e3d3300d7 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -841,47 +841,5 @@ public List getSupportedChannels() { return channels; } - public boolean getModeCapability(String mode) { - String ret = doStringCommand("GET_CAPABILITY modes"); - if (!TextUtils.isEmpty(ret)) { - String[] tokens = ret.split(" "); - for (String t : tokens) { - if (t.compareTo(mode) == 0) - return true; - } - } - return false; - } - - public List getSupportedChannels() { - boolean ibssAllowed; - List channels = new ArrayList(); - String ret = doStringCommand("GET_CAPABILITY channels"); - - if (!TextUtils.isEmpty(ret)) { - String[] lines = ret.split("\n"); - for (String l : lines) { - if (l.startsWith("Mode") || TextUtils.isEmpty(l)) continue; - - String[] tokens = l.split(" "); - if (tokens.length < 4) continue; - - if (tokens.length == 6 && tokens[5].contains("NO_IBSS")) - ibssAllowed = false; - else - ibssAllowed = true; - - try { - WifiChannel ch = new WifiChannel(Integer.parseInt(tokens[1]), Integer.parseInt(tokens[3]), ibssAllowed); - if (!channels.contains(ch)) - channels.add(ch); - } catch (java.lang.NumberFormatException e) { - Log.d(mTAG, "Can't parse: " + l); - } - } - } - return channels; - } - public native static boolean setMode(int mode); } From 4299692aab8b626885260c07b9970876d4fb9324 Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Sat, 20 Jul 2013 15:38:25 +0100 Subject: [PATCH 06/31] revert some changes --- wifi/java/android/net/wifi/WifiManager.java | 41 +++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index d62e3d2e28b..27cea3e5b5a 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -840,6 +840,23 @@ public void setFrequencyBand(int band, boolean persist) { } catch (RemoteException e) { } } + /** + * Get the operational frequency band. + * @return One of + * {@link #WIFI_FREQUENCY_BAND_AUTO}, + * {@link #WIFI_FREQUENCY_BAND_5GHZ}, + * {@link #WIFI_FREQUENCY_BAND_2GHZ} or + * {@code -1} on failure. + * @hide + */ + public int getFrequencyBand() { + try { + return mService.getFrequencyBand(); + } catch (RemoteException e) { + return -1; + } + } + /** * Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz) @@ -880,6 +897,30 @@ public List getSupportedChannels() { } } + /** + * Check if the chipset supports IBSS (Adhoc) mode + * @return {@code true} if supported, {@code false} otherwise. + */ + public boolean isIbssSupported() { + try { + return mService.isIbssSupported(); + } catch (RemoteException e) { + return false; + } + } + + /** + * Get a list of supported channels / frequencies + * @return a List of WifiChannels + * @hide + */ + public List getSupportedChannels() { + try { + return mService.getSupportedChannels(); + } catch (RemoteException e) { + return null; + } + } /** * Return the DHCP-assigned addresses from the last successful DHCP request, From 4063b3f6e524223dd9d8c45c2db58d39a3f56201 Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Sat, 20 Jul 2013 16:09:34 +0100 Subject: [PATCH 07/31] testing a few changes --- wifi/java/android/net/wifi/WifiManager.java | 25 --------------------- 1 file changed, 25 deletions(-) diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 27cea3e5b5a..28d4cb8623e 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -897,31 +897,6 @@ public List getSupportedChannels() { } } - /** - * Check if the chipset supports IBSS (Adhoc) mode - * @return {@code true} if supported, {@code false} otherwise. - */ - public boolean isIbssSupported() { - try { - return mService.isIbssSupported(); - } catch (RemoteException e) { - return false; - } - } - - /** - * Get a list of supported channels / frequencies - * @return a List of WifiChannels - * @hide - */ - public List getSupportedChannels() { - try { - return mService.getSupportedChannels(); - } catch (RemoteException e) { - return null; - } - } - /** * Return the DHCP-assigned addresses from the last successful DHCP request, * if any. From e293130f5a526ce37f8d98d0a42ea775fa4f7f86 Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Sat, 20 Jul 2013 17:35:11 +0100 Subject: [PATCH 08/31] remove more duplicate entries --- services/java/com/android/server/WifiService.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 7b3898497b3..3a7392528a4 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -963,21 +963,6 @@ public List getSupportedChannels() { } } - /** - * Is Ad-Hoc (IBSS) mode supported by the driver? - * Will only return correct results when we have reached WIFI_STATE_ENABLED - * @return {@code true} if IBSS mode is supported, {@code false} if not - */ - public boolean isIbssSupported() { - enforceAccessPermission(); - if (mWifiStateMachineChannel != null) { - return (mWifiStateMachine.syncIsIbssSupported(mWifiStateMachineChannel) == 1); - } else { - Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); - return false; - } - } - /** * Return the DHCP-assigned addresses from the last successful DHCP request, * if any. From d27f4b5c37fbe88334bd821a7a90895d28c41bfe Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Sat, 10 Aug 2013 17:48:21 +0100 Subject: [PATCH 09/31] add ADB over WiFi --- core/java/android/provider/Settings.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 2b098ec3ffb..88c717a3fd7 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5569,6 +5569,12 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val @Deprecated public static final String ADB_ENABLED = Global.ADB_ENABLED; + /** + * The TCP/IP port to run ADB on, or -1 for USB + * @hide + */ + public static final String ADB_PORT = "adb_port"; + /** * Whether to display the ADB notification. * @hide From 0be9d23267ab4c43258a67322fcf970ec451efec Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Thu, 15 Aug 2013 01:29:10 +0100 Subject: [PATCH 10/31] fix wifi over adb --- .../java/com/android/server/SystemServer.java | 16 ++++++++++++++++ .../com/android/server/usb/UsbDeviceManager.java | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 9e4debad76e..d0d29e0235a 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -28,6 +28,8 @@ import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.res.Configuration; +import android.database.ContentObserver; +import android.database.Cursor; import android.media.AudioService; import android.net.wifi.p2p.WifiP2pService; import android.os.Handler; @@ -40,6 +42,7 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; +import android.provider.Settings; import android.server.search.SearchManagerService; import android.service.dreams.DreamService; import android.util.DisplayMetrics; @@ -88,6 +91,19 @@ void reportWtf(String msg, Throwable e) { Log.wtf(TAG, "BOOT FAILURE " + msg, e); } + private class AdbPortObserver extends ContentObserver { + public AdbPortObserver() { + super(null); + } + @Override + public void onChange(boolean selfChange) { + int adbPort = Settings.Secure.getInt(mContentResolver, + Settings.Secure.ADB_PORT, 0); + // setting this will control whether ADB runs on TCP/IP or USB + SystemProperties.set("service.adb.tcp.port", Integer.toString(adbPort)); + } + } + @Override public void run() { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java index c8356a39e5e..5d962b960fe 100644 --- a/services/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/java/com/android/server/usb/UsbDeviceManager.java @@ -392,6 +392,10 @@ public void onChange(boolean selfChange) { } ); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ADB_PORT), + false, new AdbSettingsObserver()); + // Watch for USB configuration changes mUEventObserver.startObserving(USB_STATE_MATCH); mUEventObserver.startObserving(ACCESSORY_START_MATCH); From 68fea061e6053b1eca95c3e53a086f7030972431 Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Thu, 15 Aug 2013 12:43:00 +0100 Subject: [PATCH 11/31] change dalvik location --- cmds/installd/commands.c | 16 +++++++++++++--- cmds/installd/installd.c | 5 +++++ cmds/installd/installd.h | 4 ++++ cmds/installd/utils.c | 6 +++++- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index 0582cbb8f0a..2e5f360cae8 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -24,6 +24,7 @@ /* Directory records that are used in execution of commands. */ dir_rec_t android_data_dir; +dir_rec_t android_datadata_dir; dir_rec_t android_asec_dir; dir_rec_t android_app_dir; dir_rec_t android_app_private_dir; @@ -600,6 +601,7 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src) char *tmp; int srclen; int dstlen; + char dexopt_data_only[PROPERTY_VALUE_MAX]; srclen = strlen(src); @@ -612,7 +614,15 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src) return -1; } - dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) + + const char *cache_path = DALVIK_CACHE_PREFIX; + if (!strncmp(src, "/system", 7)) { + property_get("dalvik.vm.dexopt-data-only", dexopt_data_only, ""); + if (strcmp(dexopt_data_only, "1") != 0) { + cache_path = DALVIK_SYSTEM_CACHE_PREFIX; + } + } + + dstlen = srclen + strlen(cache_path) + strlen(DALVIK_CACHE_POSTFIX) + 1; if (dstlen > PKG_PATH_MAX) { @@ -620,11 +630,11 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src) } sprintf(path,"%s%s%s", - DALVIK_CACHE_PREFIX, + cache_path, src + 1, /* skip the leading / */ DALVIK_CACHE_POSTFIX); - for(tmp = path + strlen(DALVIK_CACHE_PREFIX); *tmp; tmp++) { + for(tmp = path + strlen(cache_path); *tmp; tmp++) { if (*tmp == '/') { *tmp = '@'; } diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c index ae8611786d2..74643aca9ca 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -275,6 +275,11 @@ int initialize_globals() { return -1; } + // Get the android datadata directory. + if (copy_and_append(&android_datadata_dir, &android_data_dir, DATA_SUBDIR) < 0) { + return -1; + } + // Get the android app directory. if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) { return -1; diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index 04498efab6e..8bce669bdcb 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -60,6 +60,8 @@ #define CACHE_DIR_POSTFIX "/cache" +#define DATA_SUBDIR "data/" // sub-directory under ANDROID_DATA + #define APP_SUBDIR "app/" // sub-directory under ANDROID_DATA #define APP_LIB_SUBDIR "app-lib/" // sub-directory under ANDROID_DATA @@ -72,6 +74,7 @@ #define DALVIK_CACHE_PREFIX "/data/dalvik-cache/" #define DALVIK_CACHE_POSTFIX "/classes.dex" +#define DALVIK_SYSTEM_CACHE_PREFIX "/cache/dalvik-cache/" #define UPDATE_COMMANDS_DIR_PREFIX "/system/etc/updatecmds/" @@ -97,6 +100,7 @@ extern dir_rec_t android_app_dir; extern dir_rec_t android_app_private_dir; extern dir_rec_t android_app_lib_dir; extern dir_rec_t android_data_dir; +extern dir_rec_t android_datadata_dir; extern dir_rec_t android_asec_dir; extern dir_rec_t android_media_dir; extern dir_rec_array_t android_system_dirs; diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c index 625a35efec9..154a2f87e5e 100644 --- a/cmds/installd/utils.c +++ b/cmds/installd/utils.c @@ -362,7 +362,11 @@ int lookup_media_dir(char basepath[PATH_MAX], const char *dir) int64_t data_disk_free() { struct statfs sfs; - if (statfs(android_data_dir.path, &sfs) == 0) { + /* Scanning /data/data because on some devices, it's on a different partition + * and scanning /data will yield the incorrect result. (This function is only + * used for freeing space on /data/data so it is okay to be more specific.) + */ + if (statfs(android_datadata_dir.path, &sfs) == 0) { return sfs.f_bavail * sfs.f_bsize; } else { ALOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno)); From 4cd540002857b17b88fed22adc03287ba201542b Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Mon, 26 Aug 2013 03:07:53 +0100 Subject: [PATCH 12/31] revert changes --- cmds/installd/commands.c | 16 +++------------- cmds/installd/installd.c | 14 ++++---------- cmds/installd/installd.h | 8 ++------ cmds/installd/utils.c | 6 +----- 4 files changed, 10 insertions(+), 34 deletions(-) diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index 2e5f360cae8..0582cbb8f0a 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -24,7 +24,6 @@ /* Directory records that are used in execution of commands. */ dir_rec_t android_data_dir; -dir_rec_t android_datadata_dir; dir_rec_t android_asec_dir; dir_rec_t android_app_dir; dir_rec_t android_app_private_dir; @@ -601,7 +600,6 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src) char *tmp; int srclen; int dstlen; - char dexopt_data_only[PROPERTY_VALUE_MAX]; srclen = strlen(src); @@ -614,15 +612,7 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src) return -1; } - const char *cache_path = DALVIK_CACHE_PREFIX; - if (!strncmp(src, "/system", 7)) { - property_get("dalvik.vm.dexopt-data-only", dexopt_data_only, ""); - if (strcmp(dexopt_data_only, "1") != 0) { - cache_path = DALVIK_SYSTEM_CACHE_PREFIX; - } - } - - dstlen = srclen + strlen(cache_path) + + dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) + strlen(DALVIK_CACHE_POSTFIX) + 1; if (dstlen > PKG_PATH_MAX) { @@ -630,11 +620,11 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src) } sprintf(path,"%s%s%s", - cache_path, + DALVIK_CACHE_PREFIX, src + 1, /* skip the leading / */ DALVIK_CACHE_POSTFIX); - for(tmp = path + strlen(cache_path); *tmp; tmp++) { + for(tmp = path + strlen(DALVIK_CACHE_PREFIX); *tmp; tmp++) { if (*tmp == '/') { *tmp = '@'; } diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c index 74643aca9ca..21d674a03bb 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -31,7 +31,7 @@ static int do_ping(char **arg, char reply[REPLY_MAX]) static int do_install(char **arg, char reply[REPLY_MAX]) { - return install(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); /* pkgname, uid, gid, seinfo */ + return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */ } static int do_dexopt(char **arg, char reply[REPLY_MAX]) @@ -103,8 +103,7 @@ static int do_rm_user_data(char **arg, char reply[REPLY_MAX]) static int do_mk_user_data(char **arg, char reply[REPLY_MAX]) { - return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); - /* pkgname, uid, userid, seinfo */ + return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, userid */ } static int do_rm_user(char **arg, char reply[REPLY_MAX]) @@ -135,7 +134,7 @@ struct cmdinfo { struct cmdinfo cmds[] = { { "ping", 0, do_ping }, - { "install", 4, do_install }, + { "install", 3, do_install }, { "dexopt", 3, do_dexopt }, { "movedex", 2, do_move_dex }, { "rmdex", 1, do_rm_dex }, @@ -148,7 +147,7 @@ struct cmdinfo cmds[] = { { "rmuserdata", 2, do_rm_user_data }, { "movefiles", 0, do_movefiles }, { "linklib", 3, do_linklib }, - { "mkuserdata", 4, do_mk_user_data }, + { "mkuserdata", 3, do_mk_user_data }, { "rmuser", 1, do_rm_user }, { "cloneuserdata", 3, do_clone_user_data }, }; @@ -275,11 +274,6 @@ int initialize_globals() { return -1; } - // Get the android datadata directory. - if (copy_and_append(&android_datadata_dir, &android_data_dir, DATA_SUBDIR) < 0) { - return -1; - } - // Get the android app directory. if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) { return -1; diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index 8bce669bdcb..0500c23fa6a 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -60,8 +60,6 @@ #define CACHE_DIR_POSTFIX "/cache" -#define DATA_SUBDIR "data/" // sub-directory under ANDROID_DATA - #define APP_SUBDIR "app/" // sub-directory under ANDROID_DATA #define APP_LIB_SUBDIR "app-lib/" // sub-directory under ANDROID_DATA @@ -74,7 +72,6 @@ #define DALVIK_CACHE_PREFIX "/data/dalvik-cache/" #define DALVIK_CACHE_POSTFIX "/classes.dex" -#define DALVIK_SYSTEM_CACHE_PREFIX "/cache/dalvik-cache/" #define UPDATE_COMMANDS_DIR_PREFIX "/system/etc/updatecmds/" @@ -100,7 +97,6 @@ extern dir_rec_t android_app_dir; extern dir_rec_t android_app_private_dir; extern dir_rec_t android_app_lib_dir; extern dir_rec_t android_data_dir; -extern dir_rec_t android_datadata_dir; extern dir_rec_t android_asec_dir; extern dir_rec_t android_media_dir; extern dir_rec_array_t android_system_dirs; @@ -196,12 +192,12 @@ int ensure_media_user_dirs(userid_t userid); /* commands.c */ -int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo); +int install(const char *pkgname, uid_t uid, gid_t gid); int uninstall(const char *pkgname, uid_t persona); int renamepkg(const char *oldpkgname, const char *newpkgname); int fix_uid(const char *pkgname, uid_t uid, gid_t gid); int delete_user_data(const char *pkgname, uid_t persona); -int make_user_data(const char *pkgname, uid_t uid, uid_t persona, const char* seinfo); +int make_user_data(const char *pkgname, uid_t uid, uid_t persona); int delete_persona(uid_t persona); int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy); int delete_cache(const char *pkgname, uid_t persona); diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c index 154a2f87e5e..625a35efec9 100644 --- a/cmds/installd/utils.c +++ b/cmds/installd/utils.c @@ -362,11 +362,7 @@ int lookup_media_dir(char basepath[PATH_MAX], const char *dir) int64_t data_disk_free() { struct statfs sfs; - /* Scanning /data/data because on some devices, it's on a different partition - * and scanning /data will yield the incorrect result. (This function is only - * used for freeing space on /data/data so it is okay to be more specific.) - */ - if (statfs(android_datadata_dir.path, &sfs) == 0) { + if (statfs(android_data_dir.path, &sfs) == 0) { return sfs.f_bavail * sfs.f_bsize; } else { ALOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno)); From 6b35834014bff55c2544863c31b2d86e413e9c78 Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Mon, 26 Aug 2013 21:46:45 +0100 Subject: [PATCH 13/31] bring back to same as Root-Box --- cmds/installd/installd.c | 9 +++++---- cmds/installd/installd.h | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c index 21d674a03bb..ae8611786d2 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -31,7 +31,7 @@ static int do_ping(char **arg, char reply[REPLY_MAX]) static int do_install(char **arg, char reply[REPLY_MAX]) { - return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */ + return install(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); /* pkgname, uid, gid, seinfo */ } static int do_dexopt(char **arg, char reply[REPLY_MAX]) @@ -103,7 +103,8 @@ static int do_rm_user_data(char **arg, char reply[REPLY_MAX]) static int do_mk_user_data(char **arg, char reply[REPLY_MAX]) { - return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, userid */ + return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); + /* pkgname, uid, userid, seinfo */ } static int do_rm_user(char **arg, char reply[REPLY_MAX]) @@ -134,7 +135,7 @@ struct cmdinfo { struct cmdinfo cmds[] = { { "ping", 0, do_ping }, - { "install", 3, do_install }, + { "install", 4, do_install }, { "dexopt", 3, do_dexopt }, { "movedex", 2, do_move_dex }, { "rmdex", 1, do_rm_dex }, @@ -147,7 +148,7 @@ struct cmdinfo cmds[] = { { "rmuserdata", 2, do_rm_user_data }, { "movefiles", 0, do_movefiles }, { "linklib", 3, do_linklib }, - { "mkuserdata", 3, do_mk_user_data }, + { "mkuserdata", 4, do_mk_user_data }, { "rmuser", 1, do_rm_user }, { "cloneuserdata", 3, do_clone_user_data }, }; diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index 0500c23fa6a..04498efab6e 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -192,12 +192,12 @@ int ensure_media_user_dirs(userid_t userid); /* commands.c */ -int install(const char *pkgname, uid_t uid, gid_t gid); +int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo); int uninstall(const char *pkgname, uid_t persona); int renamepkg(const char *oldpkgname, const char *newpkgname); int fix_uid(const char *pkgname, uid_t uid, gid_t gid); int delete_user_data(const char *pkgname, uid_t persona); -int make_user_data(const char *pkgname, uid_t uid, uid_t persona); +int make_user_data(const char *pkgname, uid_t uid, uid_t persona, const char* seinfo); int delete_persona(uid_t persona); int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy); int delete_cache(const char *pkgname, uid_t persona); From d790b16fd0a7b74868ce2de87e0dff26beb66ef4 Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Tue, 27 Aug 2013 20:59:02 +0100 Subject: [PATCH 14/31] bring inline with Root-Box --- wifi/java/android/net/wifi/IWifiManager.aidl | 4 ++-- wifi/java/android/net/wifi/WifiManager.java | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index f834c70c8cf..e53d6ac879c 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -70,10 +70,10 @@ interface IWifiManager boolean isDualBandSupported(); - List getSupportedChannels(); - boolean isIbssSupported(); + List getSupportedChannels(); + boolean saveConfiguration(); DhcpInfo getDhcpInfo(); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 28d4cb8623e..12701fad144 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -857,7 +857,6 @@ public int getFrequencyBand() { } } - /** * Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz) * @return {@code true} if supported, {@code false} otherwise. From 2819ccf0e7731a796d85aecccc5d491be080f8e9 Mon Sep 17 00:00:00 2001 From: drcmda Date: Sat, 3 Aug 2013 12:49:58 +0100 Subject: [PATCH 15/31] halo crash? Change-Id: Iba879efa0a5178e55f9a615d3c760e7926cf165e --- .../SystemUI/src/com/android/systemui/statusbar/halo/Halo.java | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index c2a6197aa26..2284f2cafc9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -419,6 +419,7 @@ private void loadLastNotification(boolean includeCurrentDismissable) { // If the current notification is dismissable we might want to skip it if so desired if (!includeCurrentDismissable) { if (mNotificationData.size() > 1 && mLastNotificationEntry != null && + mCurrentNotficationEntry != null && mLastNotificationEntry.notification == mCurrentNotficationEntry.notification) { boolean cancel = (mLastNotificationEntry.notification.notification.flags & Notification.FLAG_AUTO_CANCEL) == Notification.FLAG_AUTO_CANCEL; From 27a939f0048ac86db7f6e8a8fcd21def70d1e689 Mon Sep 17 00:00:00 2001 From: Anu6is Date: Sat, 10 Aug 2013 21:23:07 -0500 Subject: [PATCH 16/31] HALO Changes - Blacklisted apps don't show in HALO while scrolling * Blacklisted icons are visible in status bar but are skipped when scrolling through HALO - Added count for total number of unique notifications in HALO * Total count is visible when HALO is idle / disappears while hidden or tasking * Total count ignores pinned apps, blacklisted apps and persistent notifications - Added new icons for pinned apps and persistent notifications - Set a standard distance between message markers for HALO * Notification markers no longer spread out on larger screens * Distance between markers will be reduced if necessary to accomodate multiple notifications - Notification dismissal sync * When a notifcation is launched via HALO, it is cleared immediately from the bubble the next most recently received notification takes it place in HALO * If a notification is cleared via the notification shade, either from the status bar or the PIE menu, the notification is automatically removed form HALO - HALO will ping on screen unlock ONLY if active notificaitons exist, under the followng conditions * Status bar is hidden and HALO is hidden (Expanded Desktop Mode/Hide HALO after activity) * Protected lock screen is enabled - The android notification ticker does not "tick" when using a protected lock screen HALO usually does not update while the phone is locked Conflicts: packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java services/java/com/android/server/NotificationManagerService.java --- .../res/drawable-xhdpi/halo_pinned_app.png | Bin 0 -> 415 bytes .../drawable-xhdpi/halo_system_message.png | Bin 0 -> 4023 bytes .../res/drawable/halo_count_shape.xml | 8 + packages/SystemUI/res/layout/halo_number.xml | 27 ++ .../android/systemui/statusbar/halo/Halo.java | 388 ++++++++++++---- .../statusbar/halo/HaloProperties.java | 93 ++-- .../server/NotificationManagerService.java | 427 +++++++++++++++++- 7 files changed, 826 insertions(+), 117 deletions(-) create mode 100644 packages/SystemUI/res/drawable-xhdpi/halo_pinned_app.png create mode 100644 packages/SystemUI/res/drawable-xhdpi/halo_system_message.png create mode 100644 packages/SystemUI/res/drawable/halo_count_shape.xml diff --git a/packages/SystemUI/res/drawable-xhdpi/halo_pinned_app.png b/packages/SystemUI/res/drawable-xhdpi/halo_pinned_app.png new file mode 100644 index 0000000000000000000000000000000000000000..4a0a82e03071929cf73d5e8b2e2281f37235d9a8 GIT binary patch literal 415 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPggqc1cDaskH%nMS-Tsd%8G=RNQ(y z!&|J?fWx`B{cpZyKC|5XtK0q@3Q#YQX43VLoBP;iRyzYn0}MIb-jMJ!=IzrLix~Lo z^jRC^|8M`mu#REkMV3fGhCK=?a?NYl7~}*NX(m{=WK=VhZ+BiA`a_iE^sF7r4yer7 zX257M*T((K6|qb5jT8S_{rO_V{C-~iL&lh!i;Wx^cia&(%${wduKFbKhiJ#cm^BSu zf(uz6XjINj5Mek`@+s(m5(CGoWox-+Otdj(=BWL7@(E*fNJ6CWdn48vo{WDUv%gu# z5W;q#eYT7i(*tf*g|4ieizoX<+|N%lT>j|2Lr$)6vEIGA@7b-H=g$0frjZePm9YuRDLQmGf#~=rMS@`njxgN@xNAnM08h literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-xhdpi/halo_system_message.png b/packages/SystemUI/res/drawable-xhdpi/halo_system_message.png new file mode 100644 index 0000000000000000000000000000000000000000..9de565e522279ca5b76046dee01c7a9697ba8013 GIT binary patch literal 4023 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 + + + + + diff --git a/packages/SystemUI/res/layout/halo_number.xml b/packages/SystemUI/res/layout/halo_number.xml index 13c6958cbaa..f2642092e59 100644 --- a/packages/SystemUI/res/layout/halo_number.xml +++ b/packages/SystemUI/res/layout/halo_number.xml @@ -19,6 +19,17 @@ android:textStyle="bold" android:textSize="@dimen/halo_number_text_size"/> + + + + + + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index 2284f2cafc9..363a991568c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -30,7 +30,10 @@ import android.animation.ValueAnimator.AnimatorUpdateListener; import android.animation.Keyframe; import android.animation.PropertyValuesHolder; +import android.content.BroadcastReceiver; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; +import android.content.ComponentName; import android.content.Context; import android.content.ContentResolver; import android.content.SharedPreferences; @@ -60,6 +63,7 @@ import android.os.Vibrator; import android.os.ServiceManager; import android.provider.Settings; +import android.service.notification.INotificationListener; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.ExtendedPropertiesUtils; @@ -141,6 +145,7 @@ enum Gesture { private SettingsObserver mSettingsObserver; private GestureDetector mGestureDetector; private KeyguardManager mKeyguardManager; + private BroadcastReceiver mReceiver; private HaloEffect mEffect; private WindowManager.LayoutParams mTriggerPos; @@ -149,6 +154,8 @@ enum Gesture { private View mRoot; private View mContent, mHaloContent; + private INotificationListener mHaloListener; + private ComponentName mHaloComponent; private NotificationData.Entry mLastNotificationEntry = null; private NotificationData.Entry mCurrentNotficationEntry = null; private NotificationClicker mContentIntent, mTaskIntent; @@ -176,6 +183,7 @@ enum Gesture { private int mScreenWidth, mScreenHeight; private int mKillX, mKillY; private int mMarkerIndex = -1; + private int mDismissDelay = 100; private int oldIconIndex = -1; private float initialX = 0; @@ -232,6 +240,33 @@ public void onChange(boolean selfChange) { } } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + + if (!mAttached) { + mAttached = true; + mSettingsObserver = new SettingsObserver(new Handler()); + mSettingsObserver.observe(); + } + mHandler.postDelayed(new Runnable() { + public void run() { + final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); + mEffect.setHaloMessageNumber(0, c, false, 500, null); + } + }, 2500); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + if (mAttached) { + mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); + mAttached = false; + } + } + public Halo(Context context, AttributeSet attrs) { this(context, attrs, 0); } @@ -251,6 +286,13 @@ public Halo(Context context, AttributeSet attrs, int defStyle) { mRoot = this; mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); + IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); + + filter.addAction(Intent.ACTION_USER_PRESENT); + + mReceiver = new ScreenReceiver(); + mContext.registerReceiver(mReceiver, filter); + // Init variables mInteractionReversed = Settings.System.getInt(mContext.getContentResolver(), Settings.System.HALO_REVERSED, 1) == 1; @@ -413,19 +455,19 @@ private void updateTriggerPosition(int x, int y) { } private void loadLastNotification(boolean includeCurrentDismissable) { - if (mNotificationData.size() > 0) { - mLastNotificationEntry = mNotificationData.get(mNotificationData.size() - 1); + if (getHaloMsgCount() > 0) { + mLastNotificationEntry = mNotificationData.get(getHaloMsgIndex(getHaloMsgCount()-1,"task")); // If the current notification is dismissable we might want to skip it if so desired if (!includeCurrentDismissable) { - if (mNotificationData.size() > 1 && mLastNotificationEntry != null && + if (getHaloMsgCount() > 1 && mLastNotificationEntry != null && mCurrentNotficationEntry != null && mLastNotificationEntry.notification == mCurrentNotficationEntry.notification) { boolean cancel = (mLastNotificationEntry.notification.notification.flags & Notification.FLAG_AUTO_CANCEL) == Notification.FLAG_AUTO_CANCEL; - if (cancel) mLastNotificationEntry = mNotificationData.get(mNotificationData.size() - 2); - } else if (mNotificationData.size() == 1) { - boolean cancel = (mLastNotificationEntry.notification.notification.flags & + if (cancel) mLastNotificationEntry = mNotificationData.get(getHaloMsgIndex(getHaloMsgCount()-2,"task")); + } else if (getHaloMsgCount() == 1) { + boolean cancel = (mLastNotificationEntry.notification.getNotification().flags & Notification.FLAG_AUTO_CANCEL) == Notification.FLAG_AUTO_CANCEL; if (cancel) { // We have one notification left and it is dismissable, clear it... @@ -449,6 +491,13 @@ private void loadLastNotification(boolean includeCurrentDismissable) { public void setStatusBar(BaseStatusBar bar) { mBar = bar; + mHaloComponent = new ComponentName("HaloComponent","Halo.java"); + mHaloListener = new HaloReceiver(); + try { + mNotificationManager.registerListener(mHaloListener,mHaloComponent,0); + } catch (android.os.RemoteException ex) { + // failed to register listener + } if(ExtendedPropertiesUtils.isTablet()) { if (mBar.getTabletTicker() != null) mBar.getTabletTicker().setUpdateEvent(this); } else { @@ -459,7 +508,6 @@ public void setStatusBar(BaseStatusBar bar) { } void launchTask(NotificationClicker intent) { - // Do not launch tasks in hidden state or protected lock screen if (mState == State.HIDDEN || mState == State.SILENT || (mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure())) return; @@ -470,6 +518,7 @@ void launchTask(NotificationClicker intent) { } catch (RemoteException e) { // ... } + mDismissDelay = 1500; if (intent!= null) { intent.onClick(mRoot); @@ -593,6 +642,11 @@ public boolean onTouchEvent(MotionEvent event) { if (mOverX) { Settings.System.putInt(mContext.getContentResolver(), Settings.System.HALO_ACTIVE, 0); + try { + mNotificationManager.unregisterListener(mHaloListener,0); + } catch (android.os.RemoteException ex) { + // Failed to un-register listener + } return true; } @@ -608,7 +662,7 @@ public boolean onTouchEvent(MotionEvent event) { playSoundEffect(SoundEffectConstants.CLICK); launchTask(mTaskIntent); } - mEffect.nap(0); + mEffect.nap(100); if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 1500, HaloEffect.SLEEP_TIME, false); } else if (mGesture == Gesture.DOWN2) { @@ -624,57 +678,32 @@ public boolean onTouchEvent(MotionEvent event) { } else if (mGesture == Gesture.UP2) { // Clear all notifications playSoundEffect(SoundEffectConstants.CLICK); - + if (getHaloMsgCount()-getHidden() <1){ + mEffect.nap(1500); + if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); + } try { - mBar.getStatusBarService().onClearAllNotifications(); + mDismissDelay = 0; + mBar.getService().onClearAllNotifications(); } catch (RemoteException ex) { // system process is dead if we're here. } - - loadLastNotification(false); - - mEffect.nap(1500); - if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); } else if (mGesture == Gesture.UP1) { // Dismiss notification playSoundEffect(SoundEffectConstants.CLICK); - + if (getHaloMsgCount()-getHidden() <1){ + mEffect.nap(1500); + if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); + } if (mContentIntent != null) { try { + mDismissDelay = 0; mBar.getService().onNotificationClear(mContentIntent.mPkg, mContentIntent.mTag, mContentIntent.mId); } catch (RemoteException ex) { // system process is dead if we're here. } } - - // Find next entry - NotificationData.Entry entry = null; - if (mNotificationData.size() > 0) { - for (int i = mNotificationData.size() - 1; i >= 0; i--) { - NotificationData.Entry item = mNotificationData.get(i); - if (mCurrentNotficationEntry != null - && mCurrentNotficationEntry.notification == item.notification) { - continue; - } - boolean cancel = (item.notification.notification.flags & - Notification.FLAG_AUTO_CANCEL) == Notification.FLAG_AUTO_CANCEL; - if (cancel) { - entry = item; - break; - } - } - } - - // When no entry was found, take the last one - if (entry == null && mNotificationData.size() > 0) { - loadLastNotification(false); - } else { - tick(entry, "", 0, 0, false); - } - - mEffect.nap(1500); - if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); } else { // No gesture, just snap HALO mEffect.snap(0); @@ -767,12 +796,15 @@ public boolean onTouchEvent(MotionEvent event) { mGesture = Gesture.TASK; deltaX -= horizontalThreshold; - if (mNotificationData != null && mNotificationData.size() > 0) { - int items = mNotificationData.size(); + if (mNotificationData != null && getHaloMsgCount() > 0) { + int items = getHaloMsgCount(); - // This will be the lenght we are going to use + // This will be the length we are going to use int indexLength = ((int)(mScreenWidth * 0.85f) - mIconSize) / items; + // Set a standard (max) distance for markers. + indexLength = indexLength > 120 ? 120 : indexLength; + // Calculate index mMarkerIndex = mTickerLeft ? (items - deltaX / indexLength) - 1 : (deltaX / indexLength); @@ -849,23 +881,23 @@ public boolean onTouchEvent(MotionEvent event) { oldIconIndex = mMarkerIndex; // Make a tiny pop if not so many icons are present - if (mHapticFeedback && mNotificationData.size() < 10) mVibrator.vibrate(1); + if (mHapticFeedback && getHaloMsgCount() < 10) mVibrator.vibrate(1); + + int iconIndex = getHaloMsgIndex(mMarkerIndex, "task"); try { - if (mMarkerIndex == -1) { + if (iconIndex == -1) { mTaskIntent = null; resetIcons(); tick(mLastNotificationEntry, gestureText, 0, 250, false); - // Ping to notify the user we're back where we started - if (mEnableColor) { - mEffect.ping(mPaintHoloCustom, 0); - } else { - mEffect.ping(mPaintHolo, 0); - } + //Ping to notify the user we're back where we started + mEffect.ping(mPaintHoloBlue, 0); + final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); + mEffect.setHaloMessageNumber(0, c, false, 1000, null); } else { - setIcon(mMarkerIndex); - NotificationData.Entry entry = mNotificationData.get(mMarkerIndex); + setIcon(iconIndex); + NotificationData.Entry entry = mNotificationData.get(iconIndex); ApplicationInfo ai; try { @@ -908,6 +940,7 @@ public void cleanUp() { if (mEffect != null) mWindowManager.removeView(mEffect); // Remove resolver mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); + mContext.unregisterReceiver(mReceiver); } class HaloEffect extends HaloProperties { @@ -1102,6 +1135,12 @@ public void nap(long delay) { public void run() { updateTriggerPosition(newPos, mHaloY); }}); + mHandler.postDelayed(new Runnable() { + public void run() { + final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); + mEffect.setHaloMessageNumber(0, c, false, 2000, null); + } + }, 2000); } public void sleep(long delay, int speed, final boolean silent) { @@ -1169,11 +1208,13 @@ protected void onDraw(Canvas canvas) { // Horizontal Marker if (mGesture == Gesture.TASK) { - if (y > 0 && mNotificationData != null && mNotificationData.size() > 0) { + if (y > 0 && mNotificationData != null && getHaloMsgCount() > 0) { int pulseY = mHaloY + mIconHalfSize - mMarker.getHeight() / 2; - int items = mNotificationData.size(); + int items = getHaloMsgCount(); int indexLength = ((int)(mScreenWidth * 0.85f) - mIconSize) / items; + indexLength = indexLength > 120 ? 120 : indexLength; + for (int i = 0; i < items; i++) { float pulseX = mTickerLeft ? (mIconSize * 1.25f + indexLength * i) : (mScreenWidth - mIconSize * 1.25f - indexLength * i - mMarker.getWidth()); @@ -1239,7 +1280,13 @@ public WindowManager.LayoutParams getWMParams() { void clearTicker() { mEffect.mHaloIcon.setImageDrawable(null); mEffect.msgNumberAlphaAnimator.cancel(true); + mEffect.msgNumberFlipAnimator.cancel(true); + mEffect.tickerAnimator.cancel(true); mEffect.mHaloNumber.setAlpha(0f); + mEffect.mHaloCount.setAlpha(0f); + mEffect.mHaloPinned.setAlpha(0f); + mEffect.mHaloSystemIcon.setAlpha(0f); + mEffect.mHaloNumberIcon.setAlpha(0f); mContentIntent = null; mCurrentNotficationEntry = null; mEffect.killTicker(); @@ -1270,7 +1317,15 @@ void tick(NotificationData.Entry entry, String text, int delay, int duration, bo mEffect.invalidate(); // Set Number - mEffect.setHaloMessageNumber(n.number, alwaysFlip); + String msgType; + if (entry.notification.getPackageName().equals("com.paranoid.halo")) { + msgType = "pinned"; + } else if (!entry.notification.isClearable()) { + msgType = "system"; + } else { + msgType = "user message"; + } + mEffect.setHaloMessageNumber(n.number, -1, alwaysFlip, delay, msgType); } public void updateTicker(StatusBarNotification notification) { @@ -1286,43 +1341,204 @@ public void updateTicker(StatusBarNotification notification, String text) { } catch (android.os.RemoteException ex) { // System is dead } + if (allowed) { + for (int i = 0; i < mNotificationData.size(); i++) { + NotificationData.Entry entry = mNotificationData.get(i); - for (int i = 0; i < mNotificationData.size(); i++) { - NotificationData.Entry entry = mNotificationData.get(i); + if (entry.notification == notification) { - if (entry.notification == notification) { + // No intent, no tick ... + if (entry.notification.getNotification().contentIntent == null) return; - // No intent, no tick ... - if (entry.notification.notification.contentIntent == null) return; + mIsNotificationNew = true; + if (mLastNotificationEntry != null && notification == mLastNotificationEntry.notification) { + // Ok, this is the same notification + // Let's give it a chance though, if the text has changed we allow it + mIsNotificationNew = !mNotificationText.equals(text); + } - mIsNotificationNew = true; - if (mLastNotificationEntry != null && notification == mLastNotificationEntry.notification) { - // Ok, this is the same notification - // Let's give it a chance though, if the text has changed we allow it - mIsNotificationNew = !mNotificationText.equals(text); - } + if (mIsNotificationNew) { + mNotificationText = text; + mLastNotificationEntry = entry; - if (mIsNotificationNew) { - mNotificationText = text; - mLastNotificationEntry = entry; + if (mState != State.FIRST_RUN) { + if (mState == State.IDLE || mState == State.HIDDEN) { + if (mState == State.HIDDEN) clearTicker(); + mEffect.wake(); + mEffect.nap(HaloEffect.NAP_DELAY + HaloEffect.WAKE_TIME * 2); + if (mHideTicker) mEffect.sleep(HaloEffect.SLEEP_DELAY + HaloEffect.WAKE_TIME * 2, HaloEffect.SLEEP_TIME, false); + } - if (allowed && mState != State.FIRST_RUN) { - tick(entry, text, HaloEffect.WAKE_TIME, 1000, true); + tick(entry, text, HaloEffect.WAKE_TIME * 2, 1000, true); - // Pop while not tasking, only if notification is certified fresh - if (mEnableColor) { - if (mGesture != Gesture.TASK && mState != State.SILENT) mEffect.ping(mPaintHoloCustom, HaloEffect.WAKE_TIME); - } else { - if (mGesture != Gesture.TASK && mState != State.SILENT) mEffect.ping(mPaintHolo, HaloEffect.WAKE_TIME); + // Pop while not tasking, only if notification is certified fresh + if (mGesture != Gesture.TASK && mState != State.SILENT) mEffect.ping(mPaintHoloBlue, HaloEffect.WAKE_TIME * 2); } - if (mState == State.IDLE || mState == State.HIDDEN) { - mEffect.wake(); - mEffect.nap(HaloEffect.NAP_DELAY); - if (mHideTicker) mEffect.sleep(HaloEffect.SLEEP_DELAY, HaloEffect.SLEEP_TIME, false); + } + break; + } + } + } + } + + public int getHaloMsgCount() { + int msgs = 0; + StatusBarNotification notification; + + for(int i = 0; i < mNotificationData.size(); i++) { + notification = mNotificationData.get(i).notification; + try { + if (!mNotificationManager.isPackageAllowedForHalo(notification.getPackageName())) continue; + } catch (android.os.RemoteException ex) { + // System is dead + } + msgs += 1; + } + return msgs; + } + + public int getHaloMsgIndex(int index, String option) { + int msgIndex = 0; + StatusBarNotification notification; + + for (int i = 0; i < mNotificationData.size(); i++){ + notification = mNotificationData.get(i).notification; + try { //ignore blacklisted notifications + if (!mNotificationManager.isPackageAllowedForHalo(notification.getPackageName())) continue; + } catch (android.os.RemoteException ex) { + // System is dead + } + //if notifying the user on unlock, ignore persistent notifications + if (option.equals("notify")) { + if (!notification.isClearable()) continue; + } + + if (msgIndex == index) return i; + + msgIndex += 1; + } + return -1; + } + + public int getHidden() { + int ignore = 0; + boolean allowed = false; + boolean persistent = false; + + for (int i = 0; i < mNotificationData.size(); i++ ) { + NotificationData.Entry entry = mNotificationData.get(i); + StatusBarNotification statusNotify = entry.notification; + if (statusNotify == null) continue; + + try { + allowed = mNotificationManager.isPackageAllowedForHalo(mNotificationData.get(i).notification.getPackageName()); + } catch (android.os.RemoteException ex) { + // System is dead + } + persistent = !mNotificationData.get(i).notification.isClearable(); + // persistent notifications that were not blacklisted and pinned apps + boolean hide = (statusNotify.getPackageName().equals("com.paranoid.halo") || (allowed && persistent)); + if (hide) ignore++; + } + return ignore; + } + + private class HaloReceiver extends INotificationListener.Stub { + + public HaloReceiver(){ + //android.service.notification.NotificationListenerService + } + + @Override + public void onNotificationPosted(StatusBarNotification notification) throws RemoteException { + mHandler.postDelayed(new Runnable() { + public void run() { + final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); + mEffect.setHaloMessageNumber(0, c, false, 2000, null); + } + }, 2000); + } + + @Override + public void onNotificationRemoved(StatusBarNotification notification) throws RemoteException { + mHandler.postDelayed(new Runnable() { + public void run() { + // Find next entry + clearTicker(); + mEffect.clearAnimation(); + mNotificationText = ""; + NotificationData.Entry entry = null; + if (getHaloMsgCount() > 0) { + for (int i = getHaloMsgCount()-1; i >= 0; i--) { + NotificationData.Entry item = mNotificationData.get(getHaloMsgIndex(i,"task")); + if (mCurrentNotficationEntry != null + && mCurrentNotficationEntry.notification == item.notification) { + continue; + } + boolean cancel = (item.notification.getNotification().flags & + Notification.FLAG_AUTO_CANCEL) == Notification.FLAG_AUTO_CANCEL; + if (cancel) { + entry = item; + break; + } } } + // When no entry was found, take the last one + if (entry == null && getHaloMsgCount() > 0) { + loadLastNotification(false); + } else { + tick(entry, "", 0, 0, false); + } + final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); + mEffect.setHaloMessageNumber(0, c, false, 300, null); + if (mState != State.HIDDEN) { + mEffect.nap(1500); + if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); + } + } + }, mDismissDelay); + + mDismissDelay = 100; + } + } + + public class ScreenReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + // When screen unlocked, HALO active & Expanded desktop mode, ping HALO and load last notification. + // Because notifications are not readily visible and HALO does not "tick" on protected lock screens + if(intent.getAction().equals(Intent.ACTION_USER_PRESENT) && + Settings.System.getInt(mContext.getContentResolver(), Settings.System.HALO_ACTIVE, 0) == 1){ + if (mKeyguardManager.isKeyguardSecure() || + (Settings.System.getInt(mContext.getContentResolver(), Settings.System.EXPANDED_DESKTOP_STATE, 0) == 1 && + mState == State.HIDDEN)) { + mEffect.setHaloMessageNumber(0,0,false,0,null); + mHandler.postDelayed(new Runnable() { + public void run() { + int lastMsg = getHaloMsgCount() - getHidden(); + if (lastMsg > 0) { + NotificationData.Entry entry = mNotificationData.get(getHaloMsgIndex(lastMsg-1,"notify")); + ApplicationInfo ai; + try { + ai = mPm.getApplicationInfo( entry.notification.getPackageName(), 0); + } catch (final NameNotFoundException e) { + ai = null; + } + String text = (String) (ai != null ? mPm.getApplicationLabel(ai) : "..."); + + if (entry.notification.getNotification().tickerText != null) { + text = entry.notification.getNotification().tickerText.toString(); + } + mEffect.wake(); + mEffect.nap(HaloEffect.NAP_DELAY + HaloEffect.WAKE_TIME * 2); + if (mHideTicker) mEffect.sleep(HaloEffect.SLEEP_DELAY + HaloEffect.WAKE_TIME * 2, HaloEffect.SLEEP_TIME, false); + tick(entry, text, HaloEffect.WAKE_TIME * 2, 1000, false); + mEffect.ping(mPaintHoloBlue, HaloEffect.WAKE_TIME * 2); + } + } + }, 400); } - break; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java index e32bc3f0281..59e5d1cd6a8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java @@ -24,6 +24,7 @@ import android.graphics.drawable.Drawable; import android.os.Handler; import android.provider.Settings; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; @@ -78,8 +79,8 @@ public enum Overlay { protected RelativeLayout mHaloTickerContainer; protected View mHaloNumberView; - protected TextView mHaloNumber; - protected ImageView mHaloNumberIcon; + protected TextView mHaloNumber, mHaloCount; + protected ImageView mHaloNumberIcon, mHaloSystemIcon, mHaloPinned; protected RelativeLayout mHaloNumberContainer; private boolean mEnableColor; @@ -126,8 +127,13 @@ public HaloProperties(Context context) { mHaloNumberView = mInflater.inflate(R.layout.halo_number, null); mHaloNumberContainer = (RelativeLayout)mHaloNumberView.findViewById(R.id.container); mHaloNumber = (TextView) mHaloNumberView.findViewById(R.id.number); + mHaloCount = (TextView) mHaloNumberView.findViewById(R.id.haloCount); mHaloNumberIcon = (ImageView) mHaloNumberView.findViewById(R.id.icon); mHaloNumberIcon.setImageDrawable(mContext.getResources().getDrawable(R.drawable.halo_batch_message)); + mHaloSystemIcon = (ImageView) mHaloNumberView.findViewById(R.id.system); + mHaloSystemIcon.setImageDrawable(mContext.getResources().getDrawable(R.drawable.halo_system_message)); + mHaloPinned = (ImageView) mHaloNumberView.findViewById(R.id.pinned); + mHaloPinned.setImageDrawable(mContext.getResources().getDrawable(R.drawable.halo_pinned_app)); mFraction = Settings.System.getFloat(mContext.getContentResolver(), Settings.System.HALO_SIZE, 1.0f); @@ -173,6 +179,8 @@ public void setHaloSize(float fraction) { RelativeLayout.LayoutParams layoutParams2 = new RelativeLayout.LayoutParams(newNumberSize, newNumberSize); mHaloNumber.setLayoutParams(layoutParams2); mHaloNumber.setTextSize(TypedValue.COMPLEX_UNIT_PX, newNumberTextSize); + mHaloCount.setLayoutParams(layoutParams2); + mHaloCount.setTextSize(TypedValue.COMPLEX_UNIT_PX, newNumberTextSize); final int newSpeechTextSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_text_size) * fraction); mHaloTextViewR.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSpeechTextSize); @@ -183,6 +191,8 @@ public void setHaloSize(float fraction) { layoutParams3.addRule(RelativeLayout.CENTER_VERTICAL); layoutParams3.addRule(RelativeLayout.CENTER_HORIZONTAL); mHaloNumberIcon.setLayoutParams(layoutParams3); + mHaloSystemIcon.setLayoutParams(layoutParams3); + mHaloPinned.setLayoutParams(layoutParams3); updateResources(); updateColorView(); @@ -214,35 +224,58 @@ public int getHaloContentY() { protected CustomObjectAnimator msgNumberFlipAnimator = new CustomObjectAnimator(this); protected CustomObjectAnimator msgNumberAlphaAnimator = new CustomObjectAnimator(this); - public void setHaloMessageNumber(int value, boolean alwaysFlip) { - - // Allow transitions only if no overlay is set - if (mHaloCurrentOverlay == null) { - msgNumberAlphaAnimator.cancel(true); - float oldAlpha = mHaloNumberContainer.getAlpha(); - - mHaloNumberContainer.setAlpha(1f); - mHaloNumber.setAlpha(1f); - mHaloNumberIcon.setAlpha(0f); - if (value < 1) { - mHaloNumber.setText(""); - mHaloNumberIcon.setAlpha(1f); - } else if (value < 100) { - mHaloNumber.setText(String.valueOf(value)); - } else { - mHaloNumber.setText("+"); - } - - if (value < 1) { - msgNumberAlphaAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "alpha", 0f).setDuration(1000), - new DecelerateInterpolator(), null, 1500, null); - } - - if (!alwaysFlip && oldAlpha == 1f && (value == mHaloMessageNumber || (value > 99 && mHaloMessageNumber > 99))) return; - msgNumberFlipAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "rotationY", -180, 0).setDuration(500), - new DecelerateInterpolator(), null); + public void setHaloMessageNumber(final int value,final int msgCount, final boolean alwaysFlip, int delay, final String msgType) { + if (msgCount == 0) { + msgNumberAlphaAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "alpha", 0f).setDuration(1000), + new DecelerateInterpolator(), null, delay, null); + return; } - mHaloMessageNumber = value; + mAnimQueue.removeCallbacksAndMessages(null); + mAnimQueue.postDelayed(new Runnable() { + public void run() { + // Allow transitions only if no overlay is set + if (mHaloCurrentOverlay == null) { + msgNumberAlphaAnimator.cancel(true); + float oldAlpha = mHaloNumberContainer.getAlpha(); + + mHaloNumberContainer.setAlpha(1f); + mHaloNumber.setAlpha(1f); + mHaloCount.setAlpha(0f); + mHaloCount.setText(""); + mHaloNumberIcon.setAlpha(0f); + mHaloSystemIcon.setAlpha(0f); + mHaloPinned.setAlpha(0f); + if (msgCount > 0) { + mHaloNumber.setAlpha(0f); + mHaloCount.setText(String.valueOf(msgCount)); + mHaloCount.setAlpha(1f); + } else if (value < 1 && msgCount < 1) { + mHaloNumber.setText(""); + if (msgType != null && msgType.equals("pinned")) { + mHaloPinned.setAlpha(1f); + } else if (msgType != null && msgType.equals("system")) { + mHaloSystemIcon.setAlpha(1f); + } else { + mHaloNumberIcon.setAlpha(1f); + } + } else if (value < 100) { + Log.i("HALO", "" + value); + mHaloNumber.setText(String.valueOf(value)); + } else { + mHaloNumber.setText("+"); + } + + if (value < 1 && msgCount < 1) { + msgNumberAlphaAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "alpha", 0f).setDuration(1000), + new DecelerateInterpolator(), null, 1500, null); + } + + if (!alwaysFlip && oldAlpha == 1f && (value == mHaloMessageNumber || (value > 99 && mHaloMessageNumber > 99))) return; + msgNumberFlipAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "rotationY", -180, 0).setDuration(500), + new DecelerateInterpolator(), null); + } + mHaloMessageNumber = value; + }}, delay); } public void setHaloContentAlpha(float value) { diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index f01fca78ffa..02af3ab2765 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -457,7 +457,432 @@ private static String idDebugString(Context baseContext, String packageName, int } } - private static final class NotificationRecord + /** + * System-only API for getting a list of current (i.e. not cleared) notifications. + * + * Requires ACCESS_NOTIFICATIONS which is signature|system. + */ + @Override + public StatusBarNotification[] getActiveNotifications(String callingPkg) { + // enforce() will ensure the calling uid has the correct permission + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS, + "NotificationManagerService.getActiveNotifications"); + + StatusBarNotification[] tmp = null; + int uid = Binder.getCallingUid(); + + // noteOp will check to make sure the callingPkg matches the uid + if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg) + == AppOpsManager.MODE_ALLOWED) { + synchronized (mNotificationList) { + tmp = new StatusBarNotification[mNotificationList.size()]; + final int N = mNotificationList.size(); + for (int i=0; i installedServices = pm.queryIntentServicesAsUser( + new Intent(NotificationListenerService.SERVICE_INTERFACE), + PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, + currentUser); + + Set installed = new HashSet(); + for (int i = 0, count = installedServices.size(); i < count; i++) { + ResolveInfo resolveInfo = installedServices.get(i); + ServiceInfo info = resolveInfo.serviceInfo; + + if (!android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE.equals( + info.permission)) { + Slog.w(TAG, "Skipping notification listener service " + + info.packageName + "/" + info.name + + ": it does not require the permission " + + android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE); + continue; + } + installed.add(new ComponentName(info.packageName, info.name)); + } + + String flatOut = ""; + if (!installed.isEmpty()) { + String[] enabled = flatIn.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR); + ArrayList remaining = new ArrayList(enabled.length); + for (int i = 0; i < enabled.length; i++) { + ComponentName enabledComponent = ComponentName.unflattenFromString(enabled[i]); + if (installed.contains(enabledComponent)) { + remaining.add(enabled[i]); + } + } + flatOut = TextUtils.join(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR, remaining); + } + if (DBG) Slog.v(TAG, "flat after: " + flatOut); + if (!flatIn.equals(flatOut)) { + Settings.Secure.putStringForUser(mContext.getContentResolver(), + Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, + flatOut, currentUser); + } + } + } + + /** + * Called whenever packages change, the user switches, or ENABLED_NOTIFICATION_LISTENERS + * is altered. (For example in response to USER_SWITCHED in our broadcast receiver) + */ + void rebindListenerServices() { + final int currentUser = ActivityManager.getCurrentUser(); + String flat = Settings.Secure.getStringForUser( + mContext.getContentResolver(), + Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, + currentUser); + + NotificationListenerInfo[] toRemove = new NotificationListenerInfo[mListeners.size()]; + final ArrayList toAdd; + + synchronized (mNotificationList) { + // unbind and remove all existing listeners + toRemove = mListeners.toArray(toRemove); + + toAdd = new ArrayList(); + final HashSet newEnabled = new HashSet(); + final HashSet newPackages = new HashSet(); + + // decode the list of components + if (flat != null) { + String[] components = flat.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR); + for (int i=0; i=0; i--) { + final NotificationListenerInfo info = mListeners.get(i); + if (name.equals(info.component) + && info.userid == userid) { + // cut old connections + if (DBG) Slog.v(TAG, " disconnecting old listener: " + info.listener); + mListeners.remove(i); + if (info.connection != null) { + mContext.unbindService(info.connection); + } + } + } + + Intent intent = new Intent(NotificationListenerService.SERVICE_INTERFACE); + intent.setComponent(name); + + intent.putExtra(Intent.EXTRA_CLIENT_LABEL, + com.android.internal.R.string.notification_listener_binding_label); + intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( + mContext, 0, new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS), 0)); + + try { + if (DBG) Slog.v(TAG, "binding: " + intent); + if (!mContext.bindServiceAsUser(intent, + new ServiceConnection() { + INotificationListener mListener; + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + synchronized (mNotificationList) { + mServicesBinding.remove(servicesBindingTag); + try { + mListener = INotificationListener.Stub.asInterface(service); + NotificationListenerInfo info = new NotificationListenerInfo( + mListener, name, userid, this); + service.linkToDeath(info, 0); + mListeners.add(info); + } catch (RemoteException e) { + // already dead + } + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + Slog.v(TAG, "notification listener connection lost: " + name); + } + }, + Context.BIND_AUTO_CREATE, + new UserHandle(userid))) + { + mServicesBinding.remove(servicesBindingTag); + Slog.w(TAG, "Unable to bind listener service: " + intent); + return; + } + } catch (SecurityException ex) { + Slog.e(TAG, "Unable to bind listener service: " + intent, ex); + return; + } + } + } + + /** + * Remove a listener binder directly + */ + @Override + public void unregisterListener(INotificationListener listener, int userid) { + // no need to check permissions; if your listener binder is in the list, + // that's proof that you had permission to add it in the first place + + synchronized (mNotificationList) { + final int N = mListeners.size(); + for (int i=N-1; i>=0; i--) { + final NotificationListenerInfo info = mListeners.get(i); + if (info.listener.asBinder() == listener.asBinder() + && info.userid == userid) { + mListeners.remove(i); + if (info.connection != null) { + mContext.unbindService(info.connection); + } + } + } + } + } + + /** + * Remove a listener service for the given user by ComponentName + */ + private void unregisterListenerService(ComponentName name, int userid) { + checkCallerIsSystem(); + + synchronized (mNotificationList) { + final int N = mListeners.size(); + for (int i=N-1; i>=0; i--) { + final NotificationListenerInfo info = mListeners.get(i); + if (name.equals(info.component) + && info.userid == userid) { + mListeners.remove(i); + if (info.connection != null) { + try { + mContext.unbindService(info.connection); + } catch (IllegalArgumentException ex) { + // something happened to the service: we think we have a connection + // but it's bogus. + Slog.e(TAG, "Listener " + name + " could not be unbound: " + ex); + } + } + } + } + } + } + + /** + * asynchronously notify all listeners about a new notification + */ + private void notifyPostedLocked(NotificationRecord n) { + // make a copy in case changes are made to the underlying Notification object + final StatusBarNotification sbn = n.sbn.clone(); + for (final NotificationListenerInfo info : mListeners) { + mHandler.post(new Runnable() { + @Override + public void run() { + info.notifyPostedIfUserMatch(sbn); + }}); + } + } + + /** + * asynchronously notify all listeners about a removed notification + */ + private void notifyRemovedLocked(NotificationRecord n) { + // make a copy in case changes are made to the underlying Notification object + // NOTE: this copy is lightweight: it doesn't include heavyweight parts of the notification + final StatusBarNotification sbn_light = n.sbn.cloneLight(); + + for (final NotificationListenerInfo info : mListeners) { + mHandler.post(new Runnable() { + @Override + public void run() { + info.notifyRemovedIfUserMatch(sbn_light); + }}); + } + } + + // -- APIs to support listeners clicking/clearing notifications -- + + private NotificationListenerInfo checkListenerToken(INotificationListener listener) { + final IBinder token = listener.asBinder(); + final int N = mListeners.size(); + for (int i=0; i list = new ArrayList(); + synchronized (mNotificationList) { + final int N = mNotificationList.size(); + for (int i=0; i Date: Mon, 12 Aug 2013 14:28:21 +0100 Subject: [PATCH 17/31] HALO bugfixes - couple of problems with concurrent threads - green batch only for nap - italics gone - mdpi and & hdpi icons - statusbar-icon gaps - flipping batch when content changes - batch fadeout without flip - code style Change-Id: Idfb145eb8e220bf224dd3d0e235e3647dcc82ed9 Conflicts: packages/SystemUI/res/layout/halo_speech.xml packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java --- .../res/drawable-hdpi/halo_pinned_app.png | Bin 0 -> 1658 bytes .../res/drawable-hdpi/halo_system_message.png | Bin 0 -> 1394 bytes .../res/drawable-mdpi/halo_pinned_app.png | Bin 0 -> 1373 bytes .../res/drawable-mdpi/halo_system_message.png | Bin 0 -> 1272 bytes .../res/drawable-xhdpi/halo_pinned_app.png | Bin 415 -> 1873 bytes .../drawable-xhdpi/halo_system_message.png | Bin 4023 -> 1512 bytes packages/SystemUI/res/layout/halo_speech.xml | 6 +-- .../statusbar/halo/.goutputstream-VGJ9ZW | 0 .../statusbar/halo/CustomObjectAnimator.java | 6 ++- .../android/systemui/statusbar/halo/Halo.java | 49 ++++++------------ .../statusbar/halo/HaloProperties.java | 30 ++++++++--- 11 files changed, 46 insertions(+), 45 deletions(-) create mode 100755 packages/SystemUI/res/drawable-hdpi/halo_pinned_app.png create mode 100755 packages/SystemUI/res/drawable-hdpi/halo_system_message.png create mode 100755 packages/SystemUI/res/drawable-mdpi/halo_pinned_app.png create mode 100755 packages/SystemUI/res/drawable-mdpi/halo_system_message.png mode change 100644 => 100755 packages/SystemUI/res/drawable-xhdpi/halo_pinned_app.png mode change 100644 => 100755 packages/SystemUI/res/drawable-xhdpi/halo_system_message.png delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/halo/.goutputstream-VGJ9ZW diff --git a/packages/SystemUI/res/drawable-hdpi/halo_pinned_app.png b/packages/SystemUI/res/drawable-hdpi/halo_pinned_app.png new file mode 100755 index 0000000000000000000000000000000000000000..ee2dfbb033ce15579b490a23044c11b5a16a259b GIT binary patch literal 1658 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)yHL!FuFg7(ZG;}p~G&DAJGk0+`v9xq@ zws16q>2=9ZF3nBND}m`vf$McNz^NCM6mkoIHoK%2WtOF;xE1B+DuBIgm5JLeE;!AD z>P^Av7E4#0di8;h(Fa8=QbfaqfT;(>geO}d2cGa#^MI+n2$-y2t(a=Uz`*p*)5S5Q z;?|p)C$mKyMUL$*NsHm=kWyYGevsAHLq(;kkkhe)OKXLP-#^ACg;$;*XK=**;V$}Q z;CQgd#b2xIcE-3~LZgU_B$xsD99(f}^bMTZm^0?*h@D9si>yK2JYfu`Me=ZCc=c z)@2P$o^kux`x@rF)cfM8c6)Y-0k2nrd)L|FX$kB*xWz74xGEYobRS4B5ZGf> z$~Lc=@oYxB(y5a9V!MK8uQYzJHE@HFh{l17G2Us zw(E|EOc*5#raXVD;D5m-hrwBmQzE57jLGf({ZntQv--KqGDja|{2+LT@n?hG_8ZGR zv?SmEN;(uhv#&8nWabX;n)I-_Oota-zpj4xeQ^TQA5MpL{!N*3d+R3e`R*t(vqHIo zE3DwkRIw8I1CqB`Yh3iHTbZ>t3>BEBWgZjVIqmdwUxl+P*Qfn) z;+i0FlWE;Y%SU$JJDz-V6J)-9K>44?z302TnjaY{q)SykG_!bf`o{AaH~bp62XY87 z&u{3n>N2=n!THCza1Z~96LHJBRnju|JU4Srl=#2@^olEb)!B1c&;LkixP3$|LAS!O z{%ojcKo?I@snMgUMJ+djVl+jBi;Dl8Db!*ce4`sVklXJh9uD7s$z^ZW6= zu!%|U%(r_kS@HVHK5Ird$4=Kl3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y2=9ZF3nBND}m`vLFl!>sTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6rvIL(9V zO~LIJGn{($fsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tR1?NUNSH+KJ#>O45_&F zX69+H!ww>C!dveN-0e0OFb|5+aB?(XS1TyLK>9oDcD-8u>3Ut#f-d1ldlkAKg++Dc zUQ+wW|F2OoL+@?R#tJsOLnhD9oUymHG@g9JQ6OS*%&|3s`brKg9Snj2IWrBeW<(8GNUWH$O zkiEeD)`7rRf_(2?zs~C0SK1OF@%nj!RLMb+7Y)`Q+-AFO;7w~-d_%73^djdK=Pq=l zeHRSbw{i7{xG(yZUvy1cwn<#pbABQ_MflC>Erl;G`)u@2y-}Jl|KWqi!U9Gq&TqW8 zTDIBMe(#Do5q2oV=hp+R=JTSty1&-`Z=HJMSg% zDE`G}hP;ClH5v62IxFu#3!Qt=^Vtst#c0)^E!V?05mo=hJ1DZU&Wtp00i_>zopr03*}) An*aa+ literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-mdpi/halo_pinned_app.png b/packages/SystemUI/res/drawable-mdpi/halo_pinned_app.png new file mode 100755 index 0000000000000000000000000000000000000000..3b25cd27bde4efe7c4b9f88e4a93a50b9d56f9c9 GIT binary patch literal 1373 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y2=9ZF3nBND}m`vLFjeCsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6rXIL(9V zO~LIJC!BiqfsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tbfcGJ;1=gc+u0vF{I+w zo9TPK4?9R43ts)`x}K6%=c8pE^=%0#JWD@&b$6xM-tmO~bjyQ@&B+Lpn`Vjs+!liYE z@Sf(ngws20^cy?_F7D+pUci4P#_)84NX*M~O~w;gN~H{bu<-aD=edz##y#nQ(3+}$ z=Zh|eItos4?7XQUzT{+lYQo@w*#hU_ZKKEOQ$J$0>@{&hvmjcS8bO*=-s`k(Kc+S=-fwjQ$MhX9GvuS m`=f~8m)GPjxXQMVRf0jXXOo-o&O6&d1)is?pUXO@geCy_d-Cc4 literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-mdpi/halo_system_message.png b/packages/SystemUI/res/drawable-mdpi/halo_system_message.png new file mode 100755 index 0000000000000000000000000000000000000000..da27042a46b787c9b689aea5f1dc4f427c8b8e46 GIT binary patch literal 1272 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 ZC(hTMzt_rnH8A`bJYD@<);T3K0RZd>j`aWl diff --git a/packages/SystemUI/res/drawable-xhdpi/halo_system_message.png b/packages/SystemUI/res/drawable-xhdpi/halo_system_message.png old mode 100644 new mode 100755 index 9de565e522279ca5b76046dee01c7a9697ba8013..f031e48d191f25d3feb9bc4e531d9ef75a7ea9dc GIT binary patch literal 1512 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDi`W@uz+;N)axU~Fn+Xy|He;pk%IVs2_~;9_nB zQEUIa|m%7;QvF)%R2c)B=-RNQ(q z+umEoQKG%PNX^B>vgMCp&K@_RNrzq^72ptC`G;?%j;_DJI)U64?ckq`Z-SO`G%kpU zy3z46>2cwl)(0!wmzTfJ{}3zDHud(|d++Y;+TYmzc+cFMUuVwzK6hsD(_QN(KmT;( zWaUBzt_3i3B3IJWv4V3Cv;3O#dWrXXH5Qnx8W<-r(Nt~2VKKh|FFcT zRP4UCVgqx*`B%BBm!FvbnB~eSop4j?(>;OwM&S$7=Jz*gemL~J>a1Es?^DgK4H6Zs zuNLs?wQ5)1WlNoJmHP9{o^L_7R(Q{5uD`Z}3mAn6CY2eb&2RW%9v^OD-*p=d5GN?`>H2{DbL=wv5GErBlp<4`v%oW@S|6 z%t}+RX8o;r>&A4eQzrzHjaIeA9Vk}ruV#9+KzLDa-<7~?w;n`_vFxzZw*6|aY2~o{ z4sQ?xYk-3q%NL53;(^f@%`K#4CXHH`LYBb z^A!~y(Q#lD!G?Bf2l}^6d0byMJ*2bd{R*Zp-@n_c|B$yoYS^?plPjY5oqwyfCg+9w sV&+P`ivKQ)YzDd(jvVYx&t+g{@I1_G?(}E9C#dZ8boFyt=akR{0N8sb@c;k- literal 4023 zcmWlc2{cq~7{{+AvM-S>Ly|4wlP!#W&oWuEjO<%v`7D`AB;m6s>li~!XtM7_Cd&{L zlVzeTlf+oEZ$sg`-FxnR&%Ni|d!F}s{_peuy-6@jV>V_%W&i-#Oic`|!BHE$bj~w? z_v&l41aP1Uvo_WPYDO-tfDa5Fw~P&dv%lx7_Z3;-8>SEw$1nh3x$yU*0SXHF!IzBT zrWS^bvy1{XEH`x?IK2V@4pmbFU0c7ob@*dgmOU!wWvA)+pO)NudfcMoG?)K-@kri} z1{v+vY&ZGEzrHwpG6;>14xF65*E(M7j}Bh@Fy-MJ&>B${(CmbJaP-UgI_;I~AIn~q zenjhV%b9-4nfdtSjI)rlouO_c6^A@5rW77NB!-PVtf6!QR$KH|b^IolmPJ^BbHMUb zMrFH-s;a81B9i_|M;E5-rgQ!Cg_kKK;$|hys-Sn1_s~j9jcW6`6n|sJDZ0~Na)s5h?*@!oUTNsiMWzr z+P~^(PoKtzwwTfU9J4Yk4o6Qc0eU_Tas+BRY z@N&>gojsAoR}m>K&MnOad;r4;SHGKu_Ye>e5^7utSC5E{Jan_Ott_yt%KQ2P4%*JX0vHg|S*o-`7*0_XrJfDlog z?+pzLTS!Sx&K>CQFE=(aGJCE!zl0b3KHCwA8(j%+6%rH-ilWXZuCph4Qvc*w!8x6Y45=Qj67OeP!iZA>QM*P@2*H z_wTRzy%f{-4-N{d?^H@kNJtbCDK`A93`xU2#)bw4br=jL&(P2i3Khn!P1Y7ukJoA| z;Z9D1PEJl6Q07{N!54fyJXKwxi$j;slwdMBc?1H1tPw@sk}HAbGXYEhClkN}h|=mz zwYjr00*b(A8c}9otR6UEM#($2P6^qS{}K(&wnc~FDE|Jo|~LJ)OU3J zT8UB(wiFvr`E^r?FNRcmh?TR`o;W#`v zaG~xHm8U= z@ITs|Yo^oE(&*&!0&192iT71dSlhQ65)uq}FU7J8YzAVZeoBJ-!^6XeKGQiif{ffr z&n?W%eq5E5^rcTgL!nSgjdT0XEjv3qvgVa*N{PLf>%QK96harTm)VEM-v$5;B3jAG z*?DGWdK%7W;tWXIEL*LTJv#F}XK>eMXM{ zU9I-BXL18@>HzQ9Q2J~sxx9Whke2h@hN!b`gq@;+~D-!igTm06#|VzH0oxU(g)1}8Xx4Nk^;nvomMfe{hS_tw5t=M8!( zZj7KcFeDOb=kei21P1m778Zf|dOs*2DCkrkX?~y%0HD5ZOJ#clFcv@s0LrXy23$=P z<2=vJ!oqS+?b1f*^Fr zh?KSbj`t{ftAKztXp+I0WY!>r6YM08@Rs{rc{w@p?h5&G;F2%CjS$P^&wcr_$IQY4 z-DKS4wEkgbyn@8f+P|{>JXcpjT>Lp@aWN@!bMC#5=G3;Q0>2jm;b3EJ9a`Ph)kWkj z-ShVL#%Mx<{U&Sf#x{IzY-pgi29sNs!_`y4*8EAT(?Pbs{PpV>?ao1;#2eMs)nDJK zRA!OB0*XZZ=FOXmQ0R${C>rlU>g(_SqN=3y{Ov9Pw8X~7mJ}5g?TTeCUj?4FwY5>e zpIKmSzuCj#DafH$mJJ8n+uPKsDF+#(xevXqYXT@kL4cKI$Py;?!A)UV+WD@gV491c z-JqdZrjiln_KiVqMWlJXgL#je!pHkH?D+YR^RgFHhTIe&h3c&A>?-UW9P(|5<-_0I zlwBwf4{~_vRQlttPjKrrS}@H>13P0NY5>M)4U?Lv>cM~x6>EgaG!?fVqaR&=puxrv z_e5)SW)r}TuY{w9eb!!wDndlKczKn%bV_`jk3h@S%rq&?E=o^JbL{Bo&}Y+w2$)M` z*_2r$pV=nsm%#oT_fF4xKH#RnPp>NxvG?e`OI-JNmyq11K7JvgT}RoA_ORDx2AuS| zC9pSNpC3Nfgjm&ebbHjR$>j;PWP6w5flLzvux_t+T1ozP8lb6@HxGv;I*I5j6w zx4~+k|BTvdYf~F5T=+?5@=_Gw6Bf2$dwuf~d)A;=LuzGJOn(l@1MG3#ZYrqZNIJ0_ zv}nr=#HV=U`E7)3ju~5veM@F0*KYXbBk_4VnH>GJ^0HK- zUWvgue*b}wAOCBqtR$#Q&Ud_fr&(QHeaB8GnGw*b7;h)!$!F+s(*IU7gFqmb*=A*h zR4SEmz=t{h$L9L_`jyCy84yG)H>-NU#K3)hD@wb%qODK)`1o3bC?n`mNCxAX8Z$0p z?aq#k6%^01^E;t9`WWk4eTQRu{Qy~gf@lb~sU!*iZ3lXo(Lda7rufP`)h|WQ>qWEP zg;^C!J+(kZpZ{sKYnSG;3Qqj`J0Fnc1VsVRIJ^w~Vxm4^=>{ubv> z;?Ywp0<#m}I}cIJm%X?qEqhVOpOvc-go5Ukm6hMLN!PDmKdG=P{zA-6wUF+d1p$vW z;dE(fX$=Im&}ZQEUV?^{d-7+ODA{{*W8;ZBd&wp&_S;J_))CqVNyJT0FY+nxiQ;OL0Soqi^j!hIbNxG^~%lA(sHC6EG>mr=)pa_> zGq4!*WOrD#7)+Lu!?SD6R6ZAku9J()DFs`TFhL@{Z}lY>Rp`Uw+TWVZ3}#85l{7Z) zrbx?~{8|4wnAI_V8ZR*sB|tnkm!8g^(mSuPgV1Ej7=Q~+eO%ZsN=i!FzCY8(m0^TA z0To{JuSmy>RStGw$~XgZ_w)-q7J7!|BN(q` zn)D@dh|D#46LJqj)Mm1|T){e-`ub9I3=QM`5eUQ!Bg{&m3W~6>ji|a)NmzgITTD!h zlQ#BguSb1b9cWltgME&;XsEqJ);8XwUh3*q?@ilI5O;`Cr$>|+P`rVAM^WEkkq&SA zX-cfIf1dn4sFsnHjWUwSxo9ytx){2$7}Sf+@a7K>pepD0GqNt!~E2cO4zU0%=COdbRH3fkZ?2P`%{JM*DcI3qq*P? z%S5ZV*i@8r=~4uUQv`4-mE$W6%7PZtIoIru!F4dr2w+lNsBkfyIXz(M?(W`Gpd8@w zT+dx8%_xPHg(c;~!Zug9IuxSISvu&o8m4xsyuSV))ND}e8 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/.goutputstream-VGJ9ZW b/packages/SystemUI/src/com/android/systemui/statusbar/halo/.goutputstream-VGJ9ZW deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java index 1bacaf14898..3e3e28f96b3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java @@ -61,9 +61,13 @@ private void runAnimation(ObjectAnimator newInstance, TimeInterpolator interpola // Invalidate if (update == null) { animator.addUpdateListener(new AnimatorUpdateListener() { + float oldValue = -1f; + @Override public void onAnimationUpdate(ValueAnimator animation) { - rootView.invalidate(); + final float value = animation.getAnimatedFraction(); + if (value != oldValue) rootView.invalidate(); + oldValue = value; }}); } else { animator.addUpdateListener(update); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index 363a991568c..f436533c428 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -252,7 +252,7 @@ protected void onAttachedToWindow() { mHandler.postDelayed(new Runnable() { public void run() { final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); - mEffect.setHaloMessageNumber(0, c, false, 500, null); + mEffect.animateHaloBatch(0, c, false, 500, HaloProperties.MessageType.MESSAGE); } }, 2500); } @@ -566,19 +566,14 @@ void resetIcons() { final float originalAlpha = mContext.getResources().getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); for (int i = 0; i < mNotificationData.size(); i++) { NotificationData.Entry entry = mNotificationData.get(i); - if (entry.notification.pkg.equals("com.paranoid.halo")) { - entry.icon.setAlpha(0); - } else { - entry.icon.setAlpha(originalAlpha); - } + entry.icon.setAlpha(originalAlpha); } } void setIcon(int index) { float originalAlpha = mContext.getResources().getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); for (int i = 0; i < mNotificationData.size(); i++) { - NotificationData.Entry entry = mNotificationData.get(i); - if (entry.notification.pkg.equals("com.paranoid.halo")) continue; + NotificationData.Entry entry = mNotificationData.get(i); entry.icon.setAlpha(index == i ? 1f : originalAlpha); } } @@ -890,11 +885,6 @@ public boolean onTouchEvent(MotionEvent event) { mTaskIntent = null; resetIcons(); tick(mLastNotificationEntry, gestureText, 0, 250, false); - - //Ping to notify the user we're back where we started - mEffect.ping(mPaintHoloBlue, 0); - final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); - mEffect.setHaloMessageNumber(0, c, false, 1000, null); } else { setIcon(iconIndex); NotificationData.Entry entry = mNotificationData.get(iconIndex); @@ -1061,8 +1051,8 @@ public void ticker(String tickerText, int delay, int startDuration) { float total = TICKER_HIDE_TIME + startDuration + 1000; PropertyValuesHolder tickerUpFrames = PropertyValuesHolder.ofKeyframe("haloContentAlpha", Keyframe.ofFloat(0f, mHaloTextViewL.getAlpha()), - Keyframe.ofFloat(startDuration / total, 1f), - Keyframe.ofFloat((TICKER_HIDE_TIME + startDuration) / total, 1f), + Keyframe.ofFloat(0.1f, 1f), + Keyframe.ofFloat(0.95f, 1f), Keyframe.ofFloat(1f, 0f)); tickerAnimator.animate(ObjectAnimator.ofPropertyValuesHolder(this, tickerUpFrames).setDuration((int)total), new DecelerateInterpolator(), null, delay, null); @@ -1138,7 +1128,7 @@ public void run() { mHandler.postDelayed(new Runnable() { public void run() { final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); - mEffect.setHaloMessageNumber(0, c, false, 2000, null); + mEffect.animateHaloBatch(0, c, false, 3000, HaloProperties.MessageType.MESSAGE); } }, 2000); } @@ -1164,6 +1154,8 @@ public void unscheduleSleep() { protected void onDraw(Canvas canvas) { int state; + android.util.Log.d("PARANOID", "DRAW"); + // Ping if (mPingPaint != null) { canvas.drawCircle(mPingX, mPingY, pingRadius, mPingPaint); @@ -1317,15 +1309,15 @@ void tick(NotificationData.Entry entry, String text, int delay, int duration, bo mEffect.invalidate(); // Set Number - String msgType; + HaloProperties.MessageType msgType; if (entry.notification.getPackageName().equals("com.paranoid.halo")) { - msgType = "pinned"; + msgType = HaloProperties.MessageType.PINNED; } else if (!entry.notification.isClearable()) { - msgType = "system"; + msgType = HaloProperties.MessageType.SYSTEM; } else { - msgType = "user message"; + msgType = HaloProperties.MessageType.MESSAGE; } - mEffect.setHaloMessageNumber(n.number, -1, alwaysFlip, delay, msgType); + mEffect.animateHaloBatch(n.number, -1, alwaysFlip, delay, msgType); } public void updateTicker(StatusBarNotification notification) { @@ -1445,18 +1437,11 @@ public int getHidden() { private class HaloReceiver extends INotificationListener.Stub { - public HaloReceiver(){ - //android.service.notification.NotificationListenerService + public HaloReceiver() { } @Override public void onNotificationPosted(StatusBarNotification notification) throws RemoteException { - mHandler.postDelayed(new Runnable() { - public void run() { - final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); - mEffect.setHaloMessageNumber(0, c, false, 2000, null); - } - }, 2000); } @Override @@ -1490,7 +1475,7 @@ public void run() { tick(entry, "", 0, 0, false); } final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); - mEffect.setHaloMessageNumber(0, c, false, 300, null); + mEffect.setHaloMessageNumber(c); if (mState != State.HIDDEN) { mEffect.nap(1500); if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); @@ -1513,12 +1498,12 @@ public void onReceive(Context context, Intent intent) { if (mKeyguardManager.isKeyguardSecure() || (Settings.System.getInt(mContext.getContentResolver(), Settings.System.EXPANDED_DESKTOP_STATE, 0) == 1 && mState == State.HIDDEN)) { - mEffect.setHaloMessageNumber(0,0,false,0,null); + mEffect.animateHaloBatch(0, 0, false, 0, HaloProperties.MessageType.MESSAGE); mHandler.postDelayed(new Runnable() { public void run() { int lastMsg = getHaloMsgCount() - getHidden(); if (lastMsg > 0) { - NotificationData.Entry entry = mNotificationData.get(getHaloMsgIndex(lastMsg-1,"notify")); + NotificationData.Entry entry = mNotificationData.get(getHaloMsgIndex(lastMsg -1, "notify")); ApplicationInfo ai; try { ai = mPm.getApplicationInfo( entry.notification.getPackageName(), 0); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java index 59e5d1cd6a8..c8140ccff15 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java @@ -55,6 +55,13 @@ public enum Overlay { MESSAGE } + public enum MessageType { + MESSAGE, + PINNED, + SYSTEM + } + + private Handler mAnimQueue = new Handler(); private LayoutInflater mInflater; protected int mHaloX = 0, mHaloY = 0; @@ -91,6 +98,7 @@ public enum Overlay { private Handler mHandler; private float mFraction = 1.0f; private int mHaloMessageNumber = 0; + private MessageType mHaloMessageType = MessageType.MESSAGE; CustomObjectAnimator mHaloOverlayAnimator; @@ -224,7 +232,7 @@ public int getHaloContentY() { protected CustomObjectAnimator msgNumberFlipAnimator = new CustomObjectAnimator(this); protected CustomObjectAnimator msgNumberAlphaAnimator = new CustomObjectAnimator(this); - public void setHaloMessageNumber(final int value,final int msgCount, final boolean alwaysFlip, int delay, final String msgType) { + public void animateHaloBatch(final int value, final int msgCount, final boolean alwaysFlip, int delay, final MessageType msgType) { if (msgCount == 0) { msgNumberAlphaAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "alpha", 0f).setDuration(1000), new DecelerateInterpolator(), null, delay, null); @@ -251,9 +259,9 @@ public void run() { mHaloCount.setAlpha(1f); } else if (value < 1 && msgCount < 1) { mHaloNumber.setText(""); - if (msgType != null && msgType.equals("pinned")) { + if (msgType == MessageType.PINNED) { mHaloPinned.setAlpha(1f); - } else if (msgType != null && msgType.equals("system")) { + } else if (msgType == MessageType.SYSTEM) { mHaloSystemIcon.setAlpha(1f); } else { mHaloNumberIcon.setAlpha(1f); @@ -270,14 +278,23 @@ public void run() { new DecelerateInterpolator(), null, 1500, null); } - if (!alwaysFlip && oldAlpha == 1f && (value == mHaloMessageNumber || (value > 99 && mHaloMessageNumber > 99))) return; + // Do NOT flip when ... + if (!alwaysFlip && oldAlpha == 1f && mHaloMessageType == msgType + && (value == mHaloMessageNumber || (value > 99 && mHaloMessageNumber > 99))) return; + msgNumberFlipAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "rotationY", -180, 0).setDuration(500), new DecelerateInterpolator(), null); } mHaloMessageNumber = value; + mHaloMessageType = msgType; }}, delay); } + void setHaloMessageNumber(int count) { + mHaloCount.setText(String.valueOf(count)); + invalidate(); + } + public void setHaloContentAlpha(float value) { mHaloContentAlpha = value; mHaloTextViewL.setAlpha(value); @@ -329,9 +346,7 @@ public void setHaloOverlay(Overlay overlay, float overlayAlpha) { // Fade out number batch if (overlay != Overlay.NONE) { - msgNumberFlipAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "rotationY", 270).setDuration(500), - new DecelerateInterpolator(), null); - msgNumberAlphaAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "alpha", 0f).setDuration(500), + msgNumberAlphaAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "alpha", 0f).setDuration(100), new DecelerateInterpolator(), null); } } @@ -341,7 +356,6 @@ public void setHaloOverlay(Overlay overlay, float overlayAlpha) { } public void updateResources() { - final int iconSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_bubble_size) * mFraction); final int newSize = (int)(getWidth() * 0.9f) - iconSize; LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(newSize, LinearLayout.LayoutParams.WRAP_CONTENT); From 2a5097670e9b609458e44b8459f18998a0733de9 Mon Sep 17 00:00:00 2001 From: drcmda Date: Mon, 12 Aug 2013 18:38:53 +0100 Subject: [PATCH 18/31] HALO persistent notifications less pronounced + fixes Change-Id: Ib485468303dfd7ca7fea17d7c755a3ee4e075940 Conflicts: packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java --- .../android/systemui/statusbar/halo/Halo.java | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index f436533c428..a3c32a81ee8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -456,20 +456,18 @@ private void updateTriggerPosition(int x, int y) { private void loadLastNotification(boolean includeCurrentDismissable) { if (getHaloMsgCount() > 0) { - mLastNotificationEntry = mNotificationData.get(getHaloMsgIndex(getHaloMsgCount()-1,"task")); + mLastNotificationEntry = mNotificationData.get(getHaloMsgIndex(getHaloMsgCount() - 1, false)); // If the current notification is dismissable we might want to skip it if so desired if (!includeCurrentDismissable) { if (getHaloMsgCount() > 1 && mLastNotificationEntry != null && mCurrentNotficationEntry != null && mLastNotificationEntry.notification == mCurrentNotficationEntry.notification) { - boolean cancel = (mLastNotificationEntry.notification.notification.flags & - Notification.FLAG_AUTO_CANCEL) == Notification.FLAG_AUTO_CANCEL; - if (cancel) mLastNotificationEntry = mNotificationData.get(getHaloMsgIndex(getHaloMsgCount()-2,"task")); + if (mLastNotificationEntry.notification.isClearable()) { + mLastNotificationEntry = mNotificationData.get(getHaloMsgIndex(getHaloMsgCount() - 2, false)); + } } else if (getHaloMsgCount() == 1) { - boolean cancel = (mLastNotificationEntry.notification.getNotification().flags & - Notification.FLAG_AUTO_CANCEL) == Notification.FLAG_AUTO_CANCEL; - if (cancel) { + if (mLastNotificationEntry.notification.isClearable()) { // We have one notification left and it is dismissable, clear it... clearTicker(); return; @@ -573,8 +571,12 @@ void resetIcons() { void setIcon(int index) { float originalAlpha = mContext.getResources().getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); for (int i = 0; i < mNotificationData.size(); i++) { - NotificationData.Entry entry = mNotificationData.get(i); - entry.icon.setAlpha(index == i ? 1f : originalAlpha); + NotificationData.Entry entry = mNotificationData.get(i); + float alpha = index == i ? 1f : originalAlpha; + + // Persistent notification appear muted + if (!entry.notification.isClearable() && index != i) alpha /= 2; + entry.icon.setAlpha(alpha); } } @@ -673,7 +675,7 @@ public boolean onTouchEvent(MotionEvent event) { } else if (mGesture == Gesture.UP2) { // Clear all notifications playSoundEffect(SoundEffectConstants.CLICK); - if (getHaloMsgCount()-getHidden() <1){ + if (getHaloMsgCount()-getHidden() < 1) { mEffect.nap(1500); if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); } @@ -687,7 +689,7 @@ public boolean onTouchEvent(MotionEvent event) { } else if (mGesture == Gesture.UP1) { // Dismiss notification playSoundEffect(SoundEffectConstants.CLICK); - if (getHaloMsgCount()-getHidden() <1){ + if (getHaloMsgCount()-getHidden() < 1) { mEffect.nap(1500); if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); } @@ -878,7 +880,7 @@ public boolean onTouchEvent(MotionEvent event) { // Make a tiny pop if not so many icons are present if (mHapticFeedback && getHaloMsgCount() < 10) mVibrator.vibrate(1); - int iconIndex = getHaloMsgIndex(mMarkerIndex, "task"); + int iconIndex = getHaloMsgIndex(mMarkerIndex, false); try { if (iconIndex == -1) { @@ -1389,7 +1391,7 @@ public int getHaloMsgCount() { return msgs; } - public int getHaloMsgIndex(int index, String option) { + public int getHaloMsgIndex(int index, boolean notifyOnUnlock) { int msgIndex = 0; StatusBarNotification notification; @@ -1401,9 +1403,7 @@ public int getHaloMsgIndex(int index, String option) { // System is dead } //if notifying the user on unlock, ignore persistent notifications - if (option.equals("notify")) { - if (!notification.isClearable()) continue; - } + if (notifyOnUnlock && !notification.isClearable()) continue; if (msgIndex == index) return i; @@ -1455,14 +1455,12 @@ public void run() { NotificationData.Entry entry = null; if (getHaloMsgCount() > 0) { for (int i = getHaloMsgCount()-1; i >= 0; i--) { - NotificationData.Entry item = mNotificationData.get(getHaloMsgIndex(i,"task")); + NotificationData.Entry item = mNotificationData.get(getHaloMsgIndex(i, false)); if (mCurrentNotficationEntry != null && mCurrentNotficationEntry.notification == item.notification) { continue; } - boolean cancel = (item.notification.getNotification().flags & - Notification.FLAG_AUTO_CANCEL) == Notification.FLAG_AUTO_CANCEL; - if (cancel) { + if (item.notification.isClearable()) { entry = item; break; } @@ -1494,7 +1492,7 @@ public void onReceive(Context context, Intent intent) { // When screen unlocked, HALO active & Expanded desktop mode, ping HALO and load last notification. // Because notifications are not readily visible and HALO does not "tick" on protected lock screens if(intent.getAction().equals(Intent.ACTION_USER_PRESENT) && - Settings.System.getInt(mContext.getContentResolver(), Settings.System.HALO_ACTIVE, 0) == 1){ + Settings.System.getInt(mContext.getContentResolver(), Settings.System.HALO_ACTIVE, 0) == 1) { if (mKeyguardManager.isKeyguardSecure() || (Settings.System.getInt(mContext.getContentResolver(), Settings.System.EXPANDED_DESKTOP_STATE, 0) == 1 && mState == State.HIDDEN)) { @@ -1503,7 +1501,7 @@ public void onReceive(Context context, Intent intent) { public void run() { int lastMsg = getHaloMsgCount() - getHidden(); if (lastMsg > 0) { - NotificationData.Entry entry = mNotificationData.get(getHaloMsgIndex(lastMsg -1, "notify")); + NotificationData.Entry entry = mNotificationData.get(getHaloMsgIndex(lastMsg - 1, true)); ApplicationInfo ai; try { ai = mPm.getApplicationInfo( entry.notification.getPackageName(), 0); From c27b13105401ebb056a091d20156dc6dbc500d56 Mon Sep 17 00:00:00 2001 From: drcmda Date: Thu, 15 Aug 2013 16:12:00 +0100 Subject: [PATCH 19/31] --- HALO 2.0 --- 1. Shows the actual notifications as they come 2. Multitouch, you can interact with notifications while tasking 3. Tons of bugfixes show actual notification in halo Change-Id: I29f73c2714e3854f1d885c56baaef5552be2ff91 halo multitouch, interactive notifications Change-Id: I710fddb53688923babcb1307c05cfb0f01995855 ... Change-Id: I8bcf92df9fd5591d775083fa8e666b7d04378227 calc coords properly, margins fixed Change-Id: Ic3b107f80cd07ff50567d0591fabbad0c0b546f7 halo new content pngs up and down pointed thingies margins content size/max width ... Change-Id: I681fbefe27a87c08774291fc9a58cdafaff4d28f last bugfixes Change-Id: I5b4648f6d526f637b9bed1147f3f7be08486c4a0 copyright Change-Id: Iad42c452c948739235b7b5823b91403b134ca1cc Conflicts: packages/SystemUI/res/layout/halo_speech.xml packages/SystemUI/res/values/dimens.xml packages/SystemUI/res/values/strings.xml packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java --- .../res/drawable-nodpi/halo_speech_l_d.9.png | Bin 0 -> 2336 bytes .../res/drawable-nodpi/halo_speech_l_u.9.png | Bin 0 -> 2330 bytes .../res/drawable-nodpi/halo_speech_r_d.9.png | Bin 0 -> 2375 bytes .../res/drawable-nodpi/halo_speech_r_u.9.png | Bin 0 -> 2365 bytes packages/SystemUI/res/layout/halo_bubble.xml | 15 + packages/SystemUI/res/layout/halo_number.xml | 15 + packages/SystemUI/res/layout/halo_speech.xml | 71 ++-- packages/SystemUI/res/layout/halo_trigger.xml | 15 + packages/SystemUI/res/values/dimens.xml | 10 +- packages/SystemUI/res/values/strings.xml | 6 +- .../systemui/statusbar/BaseStatusBar.java | 46 ++- .../systemui/statusbar/NotificationData.java | 7 +- .../android/systemui/statusbar/halo/Halo.java | 302 +++++++++++------- .../statusbar/halo/HaloProperties.java | 127 ++++++-- 14 files changed, 419 insertions(+), 195 deletions(-) create mode 100755 packages/SystemUI/res/drawable-nodpi/halo_speech_l_d.9.png create mode 100755 packages/SystemUI/res/drawable-nodpi/halo_speech_l_u.9.png create mode 100755 packages/SystemUI/res/drawable-nodpi/halo_speech_r_d.9.png create mode 100755 packages/SystemUI/res/drawable-nodpi/halo_speech_r_u.9.png diff --git a/packages/SystemUI/res/drawable-nodpi/halo_speech_l_d.9.png b/packages/SystemUI/res/drawable-nodpi/halo_speech_l_d.9.png new file mode 100755 index 0000000000000000000000000000000000000000..643488fb23c6c70f242da7c26569e14571403de8 GIT binary patch literal 2336 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 literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-nodpi/halo_speech_r_d.9.png b/packages/SystemUI/res/drawable-nodpi/halo_speech_r_d.9.png new file mode 100755 index 0000000000000000000000000000000000000000..4f23ddc706e306bab7791f6c768efd973875626c GIT binary patch literal 2375 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 VG`f$%$y>V6P&{bltM2=b{0R=&<|+UH literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/layout/halo_bubble.xml b/packages/SystemUI/res/layout/halo_bubble.xml index 39d96921b97..b2a4f822fce 100644 --- a/packages/SystemUI/res/layout/halo_bubble.xml +++ b/packages/SystemUI/res/layout/halo_bubble.xml @@ -1,3 +1,18 @@ + + + + + android:layout_height="wrap_content" > + android:id="@+id/ticker_wrapper" + android:layout_width="wrap_content" + android:layout_height="@dimen/notification_min_height" > - - - - - - + android:layout_height="wrap_content" /> + + diff --git a/packages/SystemUI/res/layout/halo_trigger.xml b/packages/SystemUI/res/layout/halo_trigger.xml index f16a4a7a41d..8b66e145a2b 100644 --- a/packages/SystemUI/res/layout/halo_trigger.xml +++ b/packages/SystemUI/res/layout/halo_trigger.xml @@ -1,3 +1,18 @@ + + 24dp 16dp 14sp - 15sp - 10dp - 18dp - 7dp - 7dp + 18sp + 4dp + 13dp + 3dp + 3dp 250dp diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index d8857d67807..2105010998d 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -672,8 +672,8 @@ Hide Clear all notifications Hide and silence until woken - I am HALO. - Double-tap-drag to move me around, drag to task. - Change my behavior in the settings. + This is HALO + Move me: 2x-tap & drag + Horizontal drag to task diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 88f964196f0..22c4857f38a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -76,6 +76,7 @@ import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.widget.FrameLayout; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.PopupMenu; @@ -307,6 +308,9 @@ public void onChange(boolean selfChange) { private RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() { @Override public boolean onClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) { + + android.util.Log.d("PARANOID", "Notification click handler invoked for intent: " + pendingIntent); + if (DEBUG) { Slog.v(TAG, "Notification click handler invoked for intent: " + pendingIntent); } @@ -1515,7 +1519,32 @@ public void run() { return entry.notification; } - private Bitmap createRoundIcon(StatusBarNotification notification) { + public void prepareHaloNotification(NotificationData.Entry entry, StatusBarNotification notification, boolean update) { + + Notification notif = notification.getNotification(); + + // Get the remote view + try { + + if (!update) { + ViewGroup mainView = (ViewGroup)notif.contentView.apply(mContext, null, mOnClickHandler); + + if (mainView instanceof FrameLayout) { + entry.haloContent = mainView.getChildAt(1); + mainView.removeViewAt(1); + } else { + entry.haloContent = mainView; + } + } else { + notif.contentView.reapply(mContext, entry.haloContent, mOnClickHandler); + } + + } catch (Exception e) { + // Non uniform content? + android.util.Log.d("PARANOID", " Non uniform content?"); + } + + // Construct the round icon final float haloSize = Settings.System.getFloat(mContext.getContentResolver(), Settings.System.HALO_SIZE, 1.0f); @@ -1554,8 +1583,8 @@ private Bitmap createRoundIcon(StatusBarNotification notification) { } catch (Exception e) { // NameNotFoundException } - } - return roundIcon; + } + entry.roundIcon = roundIcon; } protected StatusBarIconView addNotificationViews(IBinder key, @@ -1580,9 +1609,9 @@ protected StatusBarIconView addNotificationViews(IBinder key, return null; } - NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView, - createRoundIcon(notification)); - entry.hide = entry.notification.pkg.equals("com.paranoid.halo"); + NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView); + prepareHaloNotification(entry, notification, false); + entry.hide = entry.notification.getPackageName().equals("com.paranoid.halo"); final PendingIntent contentIntent = notification.notification.contentIntent; if (contentIntent != null) { @@ -1743,7 +1772,7 @@ public void updateNotification(IBinder key, StatusBarNotification notification) oldEntry.floatingIntent = null; } // Update the roundIcon - oldEntry.roundIcon = createRoundIcon(notification); + prepareHaloNotification(oldEntry, notification, true); // Update the icon. final StatusBarIcon ic = new StatusBarIcon(notification.pkg, @@ -1806,6 +1835,9 @@ public void updateNotification(IBinder key, StatusBarNotification notification) mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER); } } + + // Update halo + if (mHalo != null) mHalo.update(); } // Q: What kinds of notifications should show during setup? diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java index 2f40b7e5d00..a20a6086463 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java @@ -40,6 +40,7 @@ public static final class Entry { public View row; // the outer expanded view public View content; // takes the click events and sends the PendingIntent public View expanded; // the inflated RemoteViews + public View haloContent; public ImageView largeIcon; protected boolean hide = false; protected Bitmap roundIcon; @@ -51,12 +52,6 @@ public Entry(IBinder key, StatusBarNotification n, StatusBarIconView ic) { this.notification = n; this.icon = ic; } - public Entry(IBinder key, StatusBarNotification n, StatusBarIconView ic, Bitmap ri) { - this.key = key; - this.notification = n; - this.icon = ic; - this.roundIcon = ri; - } public void setLargeView(View expandedLarge) { this.expandedLarge = expandedLarge; writeBooleanTag(row, R.id.expandable_tag, expandedLarge != null); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index a3c32a81ee8..3a9646c0ee3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -52,6 +52,7 @@ import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Point; +import android.graphics.PointF; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuff.Mode; @@ -99,6 +100,7 @@ import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.ScrollView; +import android.widget.ImageButton; import com.android.systemui.R; import com.android.systemui.statusbar.BaseStatusBar.NotificationClicker; @@ -330,7 +332,7 @@ public Halo(Context context, AttributeSet attrs, int defStyle) { WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, PixelFormat.TRANSLUCENT); @@ -404,8 +406,7 @@ private void initControl() { // Halo dock position mTickerLeft = msavePositionX == 0 ? true : false; updateTriggerPosition(msavePositionX, msavePositionY); - mEffect.mHaloTextViewL.setVisibility(mTickerLeft ? View.VISIBLE : View.GONE); - mEffect.mHaloTextViewR.setVisibility(mTickerLeft ? View.GONE : View.VISIBLE); + mEffect.updateResources(mTickerLeft); mEffect.setHaloY(msavePositionY); if (mState == State.FIRST_RUN) { @@ -414,13 +415,13 @@ private void initControl() { mHandler.postDelayed(new Runnable() { public void run() { mEffect.wake(); - tick(mLastNotificationEntry, mContext.getResources().getString(R.string.halo_tutorial1), 0, 3000, true); + mEffect.ticker(mContext.getResources().getString(R.string.halo_tutorial1), 0, 3000); mHandler.postDelayed(new Runnable() { public void run() { - tick(mLastNotificationEntry, mContext.getResources().getString(R.string.halo_tutorial2), 0, 3000, true); + mEffect.ticker(mContext.getResources().getString(R.string.halo_tutorial2), 0, 3000); mHandler.postDelayed(new Runnable() { public void run() { - tick(mLastNotificationEntry, mContext.getResources().getString(R.string.halo_tutorial3), 0, 3000, true); + mEffect.ticker(mContext.getResources().getString(R.string.halo_tutorial3), 0, 3000); mHandler.postDelayed(new Runnable() { public void run() { mState = State.IDLE; @@ -444,6 +445,10 @@ private boolean isLandscapeMod() { return mScreenWidth < mScreenHeight; } + public void update() { + if (mEffect != null) mEffect.invalidate(); + } + private void updateTriggerPosition(int x, int y) { try { mTriggerPos.x = x; @@ -480,8 +485,8 @@ private void loadLastNotification(boolean includeCurrentDismissable) { && mLastNotificationEntry.notification.notification.tickerText != null) { mNotificationText = mLastNotificationEntry.notification.notification.tickerText.toString(); } - - tick(mLastNotificationEntry, "", 0, 0, false); + + tick(mLastNotificationEntry, 0, 0, false, false); } else { clearTicker(); } @@ -489,10 +494,10 @@ private void loadLastNotification(boolean includeCurrentDismissable) { public void setStatusBar(BaseStatusBar bar) { mBar = bar; - mHaloComponent = new ComponentName("HaloComponent","Halo.java"); + mHaloComponent = new ComponentName("HaloComponent", "Halo.java"); mHaloListener = new HaloReceiver(); try { - mNotificationManager.registerListener(mHaloListener,mHaloComponent,0); + mNotificationManager.registerListener(mHaloListener, mHaloComponent, 0); } catch (android.os.RemoteException ex) { // failed to register listener } @@ -590,6 +595,8 @@ private boolean verticalGesture() { @Override public boolean onTouchEvent(MotionEvent event) { + mEffect.onTouchEvent(event); + // Prevent any kind of interaction while HALO explains itself if (mState == State.FIRST_RUN) return true; @@ -770,26 +777,25 @@ public boolean onTouchEvent(MotionEvent event) { boolean oldTickerPos = mTickerLeft; mTickerLeft = (posX + mIconHalfSize < mScreenWidth / 2); if (oldTickerPos != mTickerLeft) { - mEffect.updateResources(); - mEffect.mHaloTextViewL.setVisibility(mTickerLeft ? View.VISIBLE : View.GONE); - mEffect.mHaloTextViewR.setVisibility(mTickerLeft ? View.GONE : View.VISIBLE); + mEffect.updateResources(mTickerLeft); } } } else { // We have three basic gestures, one horizontal for switching through tasks and // two vertical for dismissing tasks or making HALO fall asleep - int deltaX = (int)(mTickerLeft ? event.getRawX() : mScreenWidth - event.getRawX()); int deltaY = (int)(mEffect.getHaloY() - event.getRawY() + mIconSize); int horizontalThreshold = (int)(mIconSize * 1.5f); int verticalThreshold = (int)(mIconSize * 0.25f); int verticalSteps = (int)(mIconSize * 0.7f); String gestureText = mNotificationText; + Gesture oldGesture = Gesture.NONE; // Switch icons if (deltaX > horizontalThreshold) { if (mGesture != Gesture.TASK) mEffect.setHaloOverlay(HaloProperties.Overlay.NONE, 0f); + oldGesture = mGesture; mGesture = Gesture.TASK; deltaX -= horizontalThreshold; @@ -811,7 +817,7 @@ public boolean onTouchEvent(MotionEvent event) { } // Up & down gestures - } else if (Math.abs(deltaY) > verticalThreshold) { + } else if (Math.abs(deltaY) > verticalThreshold * 2) { mMarkerIndex = -1; boolean gestureChanged = false; @@ -822,28 +828,32 @@ public boolean onTouchEvent(MotionEvent event) { gestureChanged = true; mEffect.setHaloOverlay(HaloProperties.Overlay.NONE, 0f); if (verticalGesture()) gestureText = ""; + oldGesture = mGesture; mGesture = Gesture.NONE; } else if (deltaY > 0) { if (deltaIndex == 1 && mGesture != Gesture.UP1) { + oldGesture = mGesture; mGesture = Gesture.UP1; gestureChanged = true; mEffect.setHaloOverlay(HaloProperties.Overlay.DISMISS, 1f); gestureText = mContext.getResources().getString(R.string.halo_dismiss); } else if (deltaIndex > 1 && mGesture != Gesture.UP2) { + oldGesture = mGesture; mGesture = Gesture.UP2; gestureChanged = true; mEffect.setHaloOverlay(HaloProperties.Overlay.CLEAR_ALL, 1f); gestureText = mContext.getResources().getString(R.string.halo_clear_all); } - } else { if (deltaIndex == 1 && mGesture != Gesture.DOWN1) { + oldGesture = mGesture; mGesture = Gesture.DOWN1; gestureChanged = true; mEffect.setHaloOverlay(mTickerLeft ? HaloProperties.Overlay.BACK_LEFT : HaloProperties.Overlay.BACK_RIGHT, 1f); gestureText = mContext.getResources().getString(R.string.halo_hide); } else if (deltaIndex > 1 && mGesture != Gesture.DOWN2) { + oldGesture = mGesture; mGesture = Gesture.DOWN2; gestureChanged = true; mEffect.setHaloOverlay(mTickerLeft ? HaloProperties.Overlay.SILENCE_LEFT @@ -854,22 +864,19 @@ public boolean onTouchEvent(MotionEvent event) { if (gestureChanged) { mMarkerIndex = -1; - - // Tasking hasn't changed, we can tick the message here - if (mMarkerIndex == oldIconIndex) { - mEffect.ticker(gestureText, 0, 250); - mEffect.updateResources(); - mEffect.invalidate(); - } + mEffect.ticker(gestureText, 0, 250); if (mHapticFeedback) mVibrator.vibrate(10); + gestureChanged = false; } } else { mMarkerIndex = -1; + if (mGesture != Gesture.NONE) { mEffect.setHaloOverlay(HaloProperties.Overlay.NONE, 0f); if (verticalGesture()) mEffect.killTicker(); } + oldGesture = mGesture; mGesture = Gesture.NONE; } @@ -878,31 +885,19 @@ public boolean onTouchEvent(MotionEvent event) { oldIconIndex = mMarkerIndex; // Make a tiny pop if not so many icons are present - if (mHapticFeedback && getHaloMsgCount() < 10) mVibrator.vibrate(1); + if (mHapticFeedback && getHaloMsgCount() < 10) mVibrator.vibrate(10); int iconIndex = getHaloMsgIndex(mMarkerIndex, false); - try { - if (iconIndex == -1) { + // Tick the first item only if we were tasking before + if (iconIndex == -1 && !verticalGesture() && oldGesture == Gesture.TASK) { mTaskIntent = null; resetIcons(); - tick(mLastNotificationEntry, gestureText, 0, 250, false); + tick(mLastNotificationEntry, 0, -1, false, true); } else { setIcon(iconIndex); NotificationData.Entry entry = mNotificationData.get(iconIndex); - - ApplicationInfo ai; - try { - ai = mPm.getApplicationInfo( entry.notification.pkg, 0); - } catch (final NameNotFoundException e) { - ai = null; - } - String text = (String) (ai != null ? mPm.getApplicationLabel(ai) : "..."); - - if (entry.notification.notification.tickerText != null) { - text = entry.notification.notification.tickerText.toString(); - } - tick(entry, text, 0, 250, false); + tick(entry, 0, -1, false, true); mTaskIntent = entry.getFloatingIntent(); } } catch (Exception e) { @@ -990,13 +985,79 @@ public HaloEffect(Context context) { (int)(mMarkerB.getHeight() * mHaloSize), true); } - mMarkerPaint.setAntiAlias(true); mMarkerPaint.setAlpha(0); xPaint.setAntiAlias(true); xPaint.setAlpha(0); - updateResources(); + updateResources(mTickerLeft); + } + + void getRawPoint(MotionEvent ev, int index, PointF point){ + final int location[] = { 0, 0 }; + mRoot.getLocationOnScreen(location); + + float x=ev.getX(index); + float y=ev.getY(index); + + double angle=Math.toDegrees(Math.atan2(y, x)); + angle+=mRoot.getRotation(); + + final float length=PointF.length(x,y); + + x=(float)(length*Math.cos(Math.toRadians(angle)))+location[0]; + y=(float)(length*Math.sin(Math.toRadians(angle)))+location[1]; + + point.set((int)x,(int)y); + } + + boolean browseView(PointF loc, Rect parent, View v) { + int posX = (int)loc.x; + int posY = (int)loc.y - mIconHalfSize / 2; + + if (v instanceof ViewGroup) { + ViewGroup vg = (ViewGroup)v; + for (int i = 0; i < vg.getChildCount(); i++) { + View sv = vg.getChildAt(i); + if (browseView(loc, parent, sv)) return true; + } + } else { + if (v.isClickable()) { + Rect r = new Rect(); + v.getHitRect(r); + + int left = tickerX + parent.left + r.left; + int top = tickerY + parent.top + r.top; + int right = tickerX + parent.left + r.right; + int bottom = tickerY + parent.top + r.bottom; + + if (posX > left && posX < right && posY > top && posY < bottom) { + v.performClick(); + playSoundEffect(SoundEffectConstants.CLICK); + if (mHapticFeedback) mVibrator.vibrate(25); + return true; + } + } + } + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + + if (event.getActionMasked() == MotionEvent.ACTION_POINTER_UP + && event.getActionIndex() == 1 ) { + + if (mCurrentNotficationEntry != null && mCurrentNotficationEntry.haloContent != null) { + Rect rootRect = new Rect(); + mHaloTickerContent.getHitRect(rootRect); + + PointF point = new PointF(); + getRawPoint(event, 1, point); + browseView(point, rootRect, mCurrentNotficationEntry.haloContent); + } + } + return false; } @Override @@ -1009,7 +1070,7 @@ public void onConfigurationChanged(Configuration newConfiguration) { // This will reset the initialization flag mInitialized = false; // Generate a new content bubble - updateResources(); + updateResources(mTickerLeft); } @Override @@ -1025,34 +1086,20 @@ public void killTicker() { } public void ticker(String tickerText, int delay, int startDuration) { - if (tickerText == null || tickerText.isEmpty()) { + if (tickerText == null || tickerText.equals("")) { killTicker(); return; } - DisplayMetrics dpm = mContext.getResources().getDisplayMetrics(); - - int shrt = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, - mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_hpadding_short), dpm); - int wide = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, - mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_hpadding_wide), dpm); - int top = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, - mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_vpadding_top), dpm); - int bttm = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, - mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_vpadding_bottom), dpm); - - mHaloTextViewR.setText(tickerText); - mHaloTextViewR.setPadding(shrt, top, wide, bttm); - mHaloTextViewR.setGravity(Gravity.CENTER_HORIZONTAL); - mHaloTextViewR.setMaxLines(2); - mHaloTextViewL.setText(tickerText); - mHaloTextViewL.setPadding(wide, top, shrt, bttm); - mHaloTextViewL.setGravity(Gravity.CENTER_HORIZONTAL); - mHaloTextViewL.setMaxLines(2); + setHaloContentHeight((int)(mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height) * 0.7f)); + mHaloTickerContent.setVisibility(View.GONE); + mHaloTextView.setVisibility(View.VISIBLE); + mHaloTextView.setText(tickerText); + updateResources(mTickerLeft); float total = TICKER_HIDE_TIME + startDuration + 1000; PropertyValuesHolder tickerUpFrames = PropertyValuesHolder.ofKeyframe("haloContentAlpha", - Keyframe.ofFloat(0f, mHaloTextViewL.getAlpha()), + Keyframe.ofFloat(0f, mHaloTextView.getAlpha()), Keyframe.ofFloat(0.1f, 1f), Keyframe.ofFloat(0.95f, 1f), Keyframe.ofFloat(1f, 0f)); @@ -1060,6 +1107,30 @@ public void ticker(String tickerText, int delay, int startDuration) { new DecelerateInterpolator(), null, delay, null); } + public void ticker(int delay, int startDuration) { + + setHaloContentHeight(mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height)); + mHaloTickerContent.setVisibility(View.VISIBLE); + mHaloTextView.setVisibility(View.GONE); + updateResources(mTickerLeft); + + if (startDuration != -1) { + // Finite tiker + float total = TICKER_HIDE_TIME + startDuration + 1000; + PropertyValuesHolder tickerUpFrames = PropertyValuesHolder.ofKeyframe("haloContentAlpha", + Keyframe.ofFloat(0f, mHaloTextView.getAlpha()), + Keyframe.ofFloat(0.1f, 1f), + Keyframe.ofFloat(0.95f, 1f), + Keyframe.ofFloat(1f, 0f)); + tickerAnimator.animate(ObjectAnimator.ofPropertyValuesHolder(this, tickerUpFrames).setDuration((int)total), + new DecelerateInterpolator(), null, delay, null); + } else { + // Infinite ticker (until killTicker() is called) + tickerAnimator.animate(ObjectAnimator.ofFloat(this, "haloContentAlpha", 1f).setDuration(250), + new DecelerateInterpolator(), null, delay, null); + } + } + public void ping(final Paint paint, final long delay) { if ((!mPingAllowed && paint != mPaintHoloRed) && mGesture != Gesture.TASK) return; @@ -1129,8 +1200,10 @@ public void run() { }}); mHandler.postDelayed(new Runnable() { public void run() { - final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); - mEffect.animateHaloBatch(0, c, false, 3000, HaloProperties.MessageType.MESSAGE); + if (mState != State.GESTURES && mState != State.DRAG) { + final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); + mEffect.animateHaloBatch(0, c, false, 3000, HaloProperties.MessageType.MESSAGE); + } } }, 2000); } @@ -1152,12 +1225,12 @@ public void unscheduleSleep() { CustomObjectAnimator contentYAnimator = new CustomObjectAnimator(this); + int tickerX, tickerY; + @Override protected void onDraw(Canvas canvas) { int state; - android.util.Log.d("PARANOID", "DRAW"); - // Ping if (mPingPaint != null) { canvas.drawCircle(mPingX, mPingY, pingRadius, mPingPaint); @@ -1165,14 +1238,16 @@ protected void onDraw(Canvas canvas) { // Content state = canvas.save(); - int ch = mGesture == Gesture.TASK ? 0 : mHaloTickerContent.getMeasuredHeight() / 2; - int cw = mHaloTickerContent.getMeasuredWidth(); + final int tickerHeight = mHaloTickerWrapper.getMeasuredHeight(); + int ch = mGesture == Gesture.TASK ? 0 : tickerHeight / 2; + int cw = mHaloTickerWrapper.getMeasuredWidth(); int y = mHaloY + mIconHalfSize - ch; + if (mGesture == Gesture.TASK) { if (mHaloY < mIconHalfSize) { - y = y + (int)(mIconSize * 0.85f); + y = y + (int)(mIconSize * 0.20f); } else { - y = y - (int)(mIconSize * 0.85f); + y = y - mIconSize; } } @@ -1181,20 +1256,6 @@ protected void onDraw(Canvas canvas) { x = mHaloX - cw - (int)(mIconSize * 0.1f); } - if (mState == State.DRAG) { - setHaloContentY(y); - } else { - if (y != getHaloContentY() && !contentYAnimator.isRunning()) { - contentYAnimator.animate(ObjectAnimator.ofInt(this, "HaloContentY", y).setDuration(300), - new DecelerateInterpolator(), null); - } - } - - state = canvas.save(); - canvas.translate(x, getHaloContentY()); - mHaloContentView.draw(canvas); - canvas.restoreToCount(state); - // X float fraction = 1 - ((float)xPaint.getAlpha()) / 255; int killyPos = (int)(mKillY - mBigRed.getWidth() / 2 - mIconSize * fraction); @@ -1210,8 +1271,8 @@ protected void onDraw(Canvas canvas) { indexLength = indexLength > 120 ? 120 : indexLength; for (int i = 0; i < items; i++) { - float pulseX = mTickerLeft ? (mIconSize * 1.25f + indexLength * i) - : (mScreenWidth - mIconSize * 1.25f - indexLength * i - mMarker.getWidth()); + float pulseX = mTickerLeft ? (mIconSize * 1.3f + indexLength * i) + : (mScreenWidth - mIconSize * 1.3f - indexLength * i - mMarker.getWidth()); boolean markerState = mTickerLeft ? mMarkerIndex >= 0 && i < items-mMarkerIndex : i <= mMarkerIndex; mMarkerPaint.setAlpha(markerState ? 255 : 100); canvas.drawBitmap(mMarker, pulseX, pulseY, mMarkerPaint); @@ -1240,6 +1301,26 @@ protected void onDraw(Canvas canvas) { canvas.drawBitmap(mMarkerB, xPos, yButtom, mMarkerPaint); } + if (mState == State.DRAG) { + setHaloContentY(y); + } else { + if (y != getHaloContentY() && !contentYAnimator.isRunning()) { + setHaloContentBackground(mTickerLeft, mGesture == Gesture.TASK && mHaloY > mIconHalfSize + ? HaloProperties.ContentStyle.CONTENT_DOWN : HaloProperties.ContentStyle.CONTENT_UP); + contentYAnimator.animate(ObjectAnimator.ofInt(this, "HaloContentY", y).setDuration(300), + new DecelerateInterpolator(), null); + } + } + + if (getHaloContentAlpha() > 0.0f) { + state = canvas.save(); + tickerX = x; + tickerY = getHaloContentY(); + canvas.translate(x, getHaloContentY()); + mHaloContentView.draw(canvas); + canvas.restoreToCount(state); + } + // Bubble state = canvas.save(); canvas.translate(mHaloX, mHaloY); @@ -1284,11 +1365,11 @@ void clearTicker() { mContentIntent = null; mCurrentNotficationEntry = null; mEffect.killTicker(); - mEffect.updateResources(); + mEffect.updateResources(mTickerLeft); mEffect.invalidate(); } - void tick(NotificationData.Entry entry, String text, int delay, int duration, boolean alwaysFlip) { + void tick(NotificationData.Entry entry, int delay, int duration, boolean alwaysFlip, boolean showContent) { if (entry == null) { clearTicker(); return; @@ -1304,10 +1385,26 @@ void tick(NotificationData.Entry entry, String text, int delay, int duration, bo // set the avatar mEffect.mHaloIcon.setImageDrawable(new BitmapDrawable(mContext.getResources(), entry.getRoundIcon())); - // Set text - if (mState != State.SILENT) mEffect.ticker(text, delay, duration); + if (showContent && mState != State.SILENT) { + if (entry.haloContent != null) { + try { + ((ViewGroup)mEffect.mHaloTickerContent).removeAllViews(); + ((ViewGroup)mEffect.mHaloTickerContent).addView(entry.haloContent); + mEffect.ticker(delay, duration); + } catch(Exception e) { + // haloContent had a view already? Let's give it one last chance ... + try { + mBar.prepareHaloNotification(entry, notification, false); + if (entry.haloContent != null) ((ViewGroup)mEffect.mHaloTickerContent).addView(entry.haloContent); + mEffect.ticker(delay, duration); + } catch(Exception ex) { + // Screw it, we're going with a simple text + mEffect.ticker(mNotificationText, delay, duration); + } + } + } + } - mEffect.updateResources(); mEffect.invalidate(); // Set Number @@ -1363,7 +1460,7 @@ public void updateTicker(StatusBarNotification notification, String text) { if (mHideTicker) mEffect.sleep(HaloEffect.SLEEP_DELAY + HaloEffect.WAKE_TIME * 2, HaloEffect.SLEEP_TIME, false); } - tick(entry, text, HaloEffect.WAKE_TIME * 2, 1000, true); + tick(entry, HaloEffect.WAKE_TIME * 2, 1000, true, true); // Pop while not tasking, only if notification is certified fresh if (mGesture != Gesture.TASK && mState != State.SILENT) mEffect.ping(mPaintHoloBlue, HaloEffect.WAKE_TIME * 2); @@ -1470,7 +1567,7 @@ public void run() { if (entry == null && getHaloMsgCount() > 0) { loadLastNotification(false); } else { - tick(entry, "", 0, 0, false); + tick(entry, 0, 0, false, false); } final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); mEffect.setHaloMessageNumber(c); @@ -1501,22 +1598,11 @@ public void onReceive(Context context, Intent intent) { public void run() { int lastMsg = getHaloMsgCount() - getHidden(); if (lastMsg > 0) { - NotificationData.Entry entry = mNotificationData.get(getHaloMsgIndex(lastMsg - 1, true)); - ApplicationInfo ai; - try { - ai = mPm.getApplicationInfo( entry.notification.getPackageName(), 0); - } catch (final NameNotFoundException e) { - ai = null; - } - String text = (String) (ai != null ? mPm.getApplicationLabel(ai) : "..."); - - if (entry.notification.getNotification().tickerText != null) { - text = entry.notification.getNotification().tickerText.toString(); - } + NotificationData.Entry entry = mNotificationData.get(getHaloMsgIndex(lastMsg - 1, true)); mEffect.wake(); mEffect.nap(HaloEffect.NAP_DELAY + HaloEffect.WAKE_TIME * 2); if (mHideTicker) mEffect.sleep(HaloEffect.SLEEP_DELAY + HaloEffect.WAKE_TIME * 2, HaloEffect.SLEEP_TIME, false); - tick(entry, text, HaloEffect.WAKE_TIME * 2, 1000, false); + tick(entry, HaloEffect.WAKE_TIME * 2, 1000, false, true); mEffect.ping(mPaintHoloBlue, HaloEffect.WAKE_TIME * 2); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java index c8140ccff15..035f1ecf3cc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java @@ -24,6 +24,9 @@ import android.graphics.drawable.Drawable; import android.os.Handler; import android.provider.Settings; +import android.graphics.ColorFilter; +import android.graphics.PorterDuff; +import android.graphics.PorterDuff.Mode; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -55,6 +58,12 @@ public enum Overlay { MESSAGE } + public enum ContentStyle { + CONTENT_NONE, + CONTENT_DOWN, + CONTENT_UP + } + public enum MessageType { MESSAGE, PINNED, @@ -67,6 +76,7 @@ public enum MessageType { protected int mHaloX = 0, mHaloY = 0; protected int mHaloContentY = 0; protected float mHaloContentAlpha = 0; + private int mHaloContentHeight = 0; private Drawable mHaloDismiss; private Drawable mHaloBackL; @@ -78,12 +88,13 @@ public enum MessageType { private Drawable mHaloMessage; private Drawable mHaloCurrentOverlay; + protected Drawable mHaloSpeechL, mHaloSpeechR, mHaloSpeechLD, mHaloSpeechRD; + protected View mHaloBubble; protected ImageView mHaloBg, mHaloBgCustom, mHaloIcon, mHaloOverlay; - protected View mHaloContentView, mHaloTickerContent; - protected TextView mHaloTextViewR, mHaloTextViewL; - protected RelativeLayout mHaloTickerContainer; + protected View mHaloContentView, mHaloTickerContent, mHaloTickerWrapper; + protected TextView mHaloTextView; protected View mHaloNumberView; protected TextView mHaloNumber, mHaloCount; @@ -100,6 +111,8 @@ public enum MessageType { private int mHaloMessageNumber = 0; private MessageType mHaloMessageType = MessageType.MESSAGE; + private boolean mLastContentStateLeft = true; + CustomObjectAnimator mHaloOverlayAnimator; public HaloProperties(Context context) { @@ -116,6 +129,13 @@ public HaloProperties(Context context) { mHaloSilenceR = mContext.getResources().getDrawable(R.drawable.halo_silence_right); mHaloMessage = mContext.getResources().getDrawable(R.drawable.halo_message); + mHaloSpeechL = mContext.getResources().getDrawable(R.drawable.halo_speech_l_u); + mHaloSpeechR = mContext.getResources().getDrawable(R.drawable.halo_speech_r_u); + mHaloSpeechLD = mContext.getResources().getDrawable(R.drawable.halo_speech_l_d); + mHaloSpeechRD = mContext.getResources().getDrawable(R.drawable.halo_speech_r_d); + + mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mHaloBubble = mInflater.inflate(R.layout.halo_bubble, null); mHaloBg = (ImageView) mHaloBubble.findViewById(R.id.halo_bg); mHaloBgCustom = (ImageView) mHaloBubble.findViewById(R.id.halo_bg_custom); @@ -123,14 +143,10 @@ public HaloProperties(Context context) { mHaloOverlay = (ImageView) mHaloBubble.findViewById(R.id.halo_overlay); mHaloContentView = mInflater.inflate(R.layout.halo_speech, null); - mHaloTickerContainer = (RelativeLayout)mHaloContentView.findViewById(R.id.container); + mHaloTickerWrapper = mHaloContentView.findViewById(R.id.ticker_wrapper); mHaloTickerContent = mHaloContentView.findViewById(R.id.ticker); - mHaloTextViewR = (TextView) mHaloTickerContent.findViewById(R.id.bubble_r); - mHaloTextViewR.setAlpha(0f); - mHaloTextViewL = (TextView) mHaloTickerContent.findViewById(R.id.bubble_l); - mHaloTextViewL.setAlpha(0f); - - updateColorView(); + mHaloTextView = (TextView) mHaloContentView.findViewById(R.id.bubble); + mHaloTextView.setAlpha(1f); mHaloNumberView = mInflater.inflate(R.layout.halo_number, null); mHaloNumberContainer = (RelativeLayout)mHaloNumberView.findViewById(R.id.container); @@ -143,6 +159,8 @@ public HaloProperties(Context context) { mHaloPinned = (ImageView) mHaloNumberView.findViewById(R.id.pinned); mHaloPinned.setImageDrawable(mContext.getResources().getDrawable(R.drawable.halo_pinned_app)); + mHaloContentHeight = mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height); + mFraction = Settings.System.getFloat(mContext.getContentResolver(), Settings.System.HALO_SIZE, 1.0f); setHaloSize(mFraction); @@ -163,16 +181,10 @@ protected void onAttachedToWindow() { } } - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - - if (mAttached) { - mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); - mAttached = false; - } - } - + int newPaddingHShort; + int newPaddingHWide; + int newPaddingVTop; + int newPaddingVBottom; public void setHaloSize(float fraction) { final int newBubbleSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_bubble_size) * fraction); @@ -182,6 +194,11 @@ public void setHaloSize(float fraction) { mHaloIcon.setLayoutParams(layoutParams); mHaloOverlay.setLayoutParams(layoutParams); + newPaddingHShort = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_hpadding_short) * fraction); + newPaddingHWide = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_hpadding_wide) * fraction); + newPaddingVTop = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_vpadding_top) * fraction); + newPaddingVBottom = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_vpadding_bottom) * fraction); + final int newNumberSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_size) * fraction); final int newNumberTextSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_text_size) * fraction); RelativeLayout.LayoutParams layoutParams2 = new RelativeLayout.LayoutParams(newNumberSize, newNumberSize); @@ -191,8 +208,7 @@ public void setHaloSize(float fraction) { mHaloCount.setTextSize(TypedValue.COMPLEX_UNIT_PX, newNumberTextSize); final int newSpeechTextSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_text_size) * fraction); - mHaloTextViewR.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSpeechTextSize); - mHaloTextViewL.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSpeechTextSize); + mHaloTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSpeechTextSize); final int newBatchIconSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_icon_size) * fraction); RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(newBatchIconSize, newBatchIconSize); @@ -202,8 +218,7 @@ public void setHaloSize(float fraction) { mHaloSystemIcon.setLayoutParams(layoutParams3); mHaloPinned.setLayoutParams(layoutParams3); - updateResources(); - updateColorView(); + updateResources(mLastContentStateLeft); } public void setHaloX(int value) { @@ -267,7 +282,6 @@ public void run() { mHaloNumberIcon.setAlpha(1f); } } else if (value < 100) { - Log.i("HALO", "" + value); mHaloNumber.setText(String.valueOf(value)); } else { mHaloNumber.setText("+"); @@ -296,6 +310,9 @@ void setHaloMessageNumber(int count) { } public void setHaloContentAlpha(float value) { + mHaloTickerWrapper.setAlpha(value); + mHaloTextView.setTextColor(mHaloTextView.getTextColors().withAlpha((int)(value * 255))); + mHaloTickerWrapper.invalidate(); mHaloContentAlpha = value; mHaloTextViewL.setAlpha(value); mHaloTextViewR.setAlpha(value); @@ -352,15 +369,46 @@ public void setHaloOverlay(Overlay overlay, float overlayAlpha) { } mHaloOverlay.setAlpha(overlayAlpha); - updateResources(); + updateResources(mLastContentStateLeft); } - public void updateResources() { - final int iconSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_bubble_size) * mFraction); - final int newSize = (int)(getWidth() * 0.9f) - iconSize; - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(newSize, LinearLayout.LayoutParams.WRAP_CONTENT); - mHaloTickerContainer.setLayoutParams(layoutParams); + private ContentStyle mLastContentStyle = ContentStyle.CONTENT_NONE; + public void setHaloContentBackground(boolean contentLeft, ContentStyle style) { + if (style != mLastContentStyle) { + // Set background + switch(style) { + case CONTENT_UP: + mHaloTickerWrapper.setBackground(contentLeft ? mHaloSpeechL : mHaloSpeechR); + break; + case CONTENT_DOWN: + mHaloTickerWrapper.setBackground(contentLeft ? mHaloSpeechLD : mHaloSpeechRD); + break; + } + // ... and override its padding + if (contentLeft) { + mHaloTickerWrapper.setPadding(newPaddingHWide, newPaddingVTop, newPaddingHShort, newPaddingVBottom); + } else { + mHaloTickerWrapper.setPadding(newPaddingHShort, newPaddingVTop, newPaddingHWide, newPaddingVBottom); + } + + mLastContentStyle = style; + } + } + + public void setHaloContentHeight(int size) { + mHaloContentHeight = size; + } + + public void updateResources(boolean contentLeft) { + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, mHaloContentHeight); + mHaloTickerWrapper.setLayoutParams(layoutParams); + + // Set background and override its padding + setHaloContentBackground(contentLeft, mLastContentStyle); + + // Measure controls mHaloContentView.measure(MeasureSpec.getSize(mHaloContentView.getMeasuredWidth()), MeasureSpec.getSize(mHaloContentView.getMeasuredHeight())); mHaloContentView.layout(0, 0, 0, 0); @@ -372,6 +420,23 @@ public void updateResources() { mHaloNumberView.measure(MeasureSpec.getSize(mHaloNumberView.getMeasuredWidth()), MeasureSpec.getSize(mHaloNumberView.getMeasuredHeight())); mHaloNumberView.layout(0, 0, 0, 0); + + // Maximal stretch for speech bubble + final int iconSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_bubble_size) * mFraction); + final int maximumWidth = (int)(getWidth() * 0.95f) - iconSize; + + if (mHaloTickerWrapper.getMeasuredWidth() > maximumWidth) { + final int optimalWidth = iconSize * 5; + final int newSize = maximumWidth > optimalWidth ? optimalWidth : maximumWidth; + layoutParams = new LinearLayout.LayoutParams(newSize, mHaloContentHeight); + mHaloTickerWrapper.setLayoutParams(layoutParams); + + mHaloContentView.measure(MeasureSpec.getSize(mHaloContentView.getMeasuredWidth()), + MeasureSpec.getSize(mHaloContentView.getMeasuredHeight())); + mHaloContentView.layout(0, 0, 0, 0); + } + + mLastContentStateLeft = contentLeft; } class SettingsObserver extends ContentObserver { From 3b515f8f3cbaf9648fbab31eae8d1cc560d0fb5e Mon Sep 17 00:00:00 2001 From: drcmda Date: Sat, 17 Aug 2013 17:40:52 +0100 Subject: [PATCH 20/31] halo, tweaking Change-Id: I35f8dc19ed5840e186989ec3cfa5529c9d39dd48 --- .../res/drawable-nodpi/halo_speech_l_d.9.png | Bin 2336 -> 2608 bytes .../res/drawable-nodpi/halo_speech_l_u.9.png | Bin 2330 -> 2560 bytes .../res/drawable-nodpi/halo_speech_r_d.9.png | Bin 2375 -> 2597 bytes .../res/drawable-nodpi/halo_speech_r_u.9.png | Bin 2365 -> 2578 bytes packages/SystemUI/res/layout/halo_speech.xml | 3 ++- packages/SystemUI/res/values/dimens.xml | 2 +- packages/SystemUI/res/values/strings.xml | 6 +++--- .../systemui/statusbar/BaseStatusBar.java | 3 --- .../android/systemui/statusbar/halo/Halo.java | 2 +- .../statusbar/halo/HaloProperties.java | 4 ++-- 10 files changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/SystemUI/res/drawable-nodpi/halo_speech_l_d.9.png b/packages/SystemUI/res/drawable-nodpi/halo_speech_l_d.9.png index 643488fb23c6c70f242da7c26569e14571403de8..9b389f784d589153e6b5c1025f8b593abfc74ebd 100755 GIT binary patch delta 1964 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 diff --git a/packages/SystemUI/res/drawable-nodpi/halo_speech_l_u.9.png b/packages/SystemUI/res/drawable-nodpi/halo_speech_l_u.9.png index 4e98c008cb1550931fac911f0827ff144f2425ff..4b038536db2ca17db3e35ecdb908576021885b46 100755 GIT binary patch delta 1915 zcmbV{X*3&%0)-O{X{#-<)iQ)wGL}SS5o(A?MC`R3OC~85QM=lgYE)6i5X4?QYKgv% zeQA}9TH0EQQl+C6##&l?J*`@%Ki<#x&O7Jb-`{u7y~W@J$t((x*<`5!A!KDLm-kXNMM14Uz!2{!nzcqsZ;dKCo0QY z!bPDwibsE^MW|?1fpu#`taX^+yM|8fj37r8tq?hSY|(znroCSW#r#t#th+hjiq}ex z&A|(7%gcTpxH9tz<2fFm!Mx*Z{d;XHB(MUXo=e}_oaJjZSS2qs^8M3y)c&DB9`5|s zwY9p(;vXCXYX3P@Wd#J(+Hxh{AIy!bT%plM?x$ZcWqUweE|{QtGK6w;5(AAOY+^b%$DGWG`tC5q) z`!L2C7HHICM0nONk~_97IF)M;1UoFn0%3I(j*`lF6i9dCtQ7UaXkV$7=s9aL}2TX~l=EMw7Z zz$B$yR60w@o?He*tCwdgIk%}NTvcG#GD`pg8zP-&c9&qSf238-C4;JAQFc3>_^LfQ7UbEVdNb_7W?|QOq6l)^A&Us`!*vl2DE&Kgz@i`33@y5t0}H! z?UfDuL&0l3Fws~cn~hOX$}eTjx$O=8%aiJsJRY{6*;Y5+hc7ap+nFy*MFtBe{^+^c z$Xi(3B%N>2DjCm>-$^2W=m@`iEvoc!$wJ{HKt(TY|Gji@Ogyh=TDBx+h3h{^SNlt` zzpK*iYuju(eMYl5EU>7)=ET}%&qFg53BR&;K~l$Uwf+|#&{xrQOlgCK6b(<#!5!Mo zO57M3)^*nRn~T1z+Y(yV(HRfp){Wm|>|4k8XZr9fZmzELfAD_@@cxg9-A3cj?Nm9 z-5Ouw47=K>E26mRx7;7n+S{=f7W1cv~Q&W!@7CpB%H=NFe<$iZF#a_S=? zD$%FsxZ;AKQV@%JdF;e~CUiTDC#kUe1}!Nxl<&iBDJi@m-g8-(2P(+u+vIq24>p?l zM$?kDuGy@2E}b2ax;PC2k@Pf1oIlwofAjG}p6*A7#gm*VGm-MFk@vS&W+yy)yjH?x zHPmTF&|PqvU6Aq-sxNMNdWfU6_4313$a#1)cI@Cwic!k)1OmLcoSYB^+o|0!4N)%9 zF+MmZw;)a;RT)vB%{*$lw{p6b)a_HX8;I9Fb1Wm)<4>PY>~JxYTMyz|VDqkil;qqR z>jioZ!lcc|XSD8|PG6?C0pGh}Bqc=@Tg`hdnc9zuH~rT1bLNWRw{oP}M%^48+&qS< zE-k6?I80YR-B{c^IogeH*?PWzn}k@p2*1hC|D=r-S8=6_jgT7Gn!cL-t{`U)<%!tT zu&}Yi>(i+nq{RKBar$w{)xs4*kKjlBvbBwR$GK6Hlb#^srS3&~QyXsHl}VAed(U2L za#64mxp3BOwh|^UJ>g)xW6g%^<;Y-p)?J~c&b>ff`!+tfv5(6WyL5h#Xv5|$kn^m5 zYmbYRm@d8l;*I?|btkWHhdc>Z$1MaaTrrL;n+|#vdyt!{;ZSs>mY!tUIl30Dt>PW( zpd<`VVBRq@)XcqJk1DkwN-te{YUzHD>g|@STB;cc&W;gbM7Xox!k)cKW7tCdi!VR> z>C5u5{R=iMF?);J>?@7>>**$~Mu~N;DD9v_+x4@dlsTJf)k>M4T3_vjj)=Mj3xC1G z?WGj)wVmV!%%5kNQdS@`K>Sk1qye@?5_%QiA)y0~ey1%f!hcXE<#PX`@}8*sX)NB^ hHVZP7I62fUAPRsrXY}e7?bQIjheEO?))PDu{{}1qVn_f0 delta 1661 zcmZ{ieLNEg1IK40ug6-*?$FHI9K%%Jc3#?SY$-2|Au(^u%e=qtGcWU2URH62oXvTy zR33&NtnSj|u~0bV42PpSB;|IrWgJg`-1BF@zrWw_U%y=KT1Yur0p58IrNCWKfOBIM z7~Drdb8aT^8yLaH-pbnQv^~bghG=C)JZcgI7lTl$Flv>{jTYaTV4`1(n;=RW8_C7+y&lo+T^ zTY?aS$_Ru{i?>=>8$D2*zIbWIT=uErOiA4=|D~PD#qRd#&6#`YEp9VOmB*advQN~@ z__D9=y~7IJ3&0x`3Y#KW*$N#66u6 z%tLU+=v-COyWaEAY4M(RZVoE4Z>@&`p)#6Y;gS6!({R>}-vyP5-ap*?J0_&J#}OHn zonuDU_h;ZBa&K4?0gre;ih~Y~&5a6|N|r)N#=|d@8`gq;NOU0{h?lC* zDw2#hpLx@52a4yP@y7(9gpsDRClmJ79#+J7y6b&#F=B#0mF_)VOFkG^4+~5@lO3rv z%*&V<4CpUH@w7WmG=f6=&I>(M^Pb4M=z1i!#er&N8#APX(M6U>jjroDZt|e%>poYq zp=u0UEeEg>57JSPLzHF&l{Y^4t`noIc5k+^?I7aVt2%JjVghN-Jd*V>!^dTtWTTI)13yAE;xlbRr)c=jG z+re@E76H*r3RjA{AI38{vTGuN^TB<2S}EgRZdpl&+EZ2`y{;dS!6F?8lp+g7CpR72 zb_RTB;Ist`^#|-ZJJ~wkId)TGjyz?Kt?8VeKQ&6UjdgFBf%rn&G)q>r4@cbs@6UYS zC%JXitYa4;sCoO7#= zkW|7sOtD{h>9_0_Eco6x-QK~4ka(azbX2vFUif=!{*E;-_~$|4Nao69(lT2^B0Zjd zgP3^a3TVaDo66p~8&8Y19Ly=X{&S16yy*SoFfsT)aKA}l@iv8-!gnj@3nRLMMi%dU zdLmmiTB`S#f75Cc;9|&PUK_5&o&2>H@9$ER(YpI0_SGtikF-qJcUGur&*5kF)Sukw zyOrMt&pUSq!f@Rwmc2^l*|Bj>_Nhxc%TYgdU}S{mPOmJ_p_()zt+Ib5j6)L`CUs)7Pz09Ie>Xfo@&Gsn#TMcrN77W4iJO*W*v`uUJ? z#u@Vk>xZ!C&t;8+Q=)Ry;4S^^qfEG?^xL+17~6DcT3AGvgST0;>8cR)tseDguCOU@u>V%MnAnv3oxem-m}S+rHD>%TW@Ww zI{7B7x*iSgn^&*x+n6a1zE2QgBI7G=j|(aPzWkMHD$T`7&!KyJbs1{j_19@+a}#uG zbZjnQ-J@sL^C3Gq^L!K3ss~nL?5!)At<$V3q^fF!PVT1x%Y+80F;wo;yih7iWp1-e zW@MOtI&>hlC-NDWVtUumPnR-n`v?5w71I<305{h

)2LxHa7gynd^=aGpXgm!#L{{H|GBkw5y diff --git a/packages/SystemUI/res/drawable-nodpi/halo_speech_r_d.9.png b/packages/SystemUI/res/drawable-nodpi/halo_speech_r_d.9.png index 4f23ddc706e306bab7791f6c768efd973875626c..f412194527f6b9c3c0339526a5a2ab83894250c7 100755 GIT binary patch delta 1952 zcmbV{dpHw}9>>R4NTN(QqA{<_Xl*VV!m-(~9Sb$LTpF7d=F(8EEtf>D8D2+kA`zp_ z{Vr5;X}uzIuuK;va;cQbQpb6o^XECwd7krqet-O)=ll8op5J%qP!%|zAVqH^>PxXp zrD*IBDMMByiDc!%3_cee9>BmwP-DV^!lMZ|8=cs&NH{H+W@T<>Z)t|c;Zc?d6y6kx zv_P6zVlh}Vl&J;I0*%J%Kz7O98~-Wm;NXBWL7;cX9F0WcO)>VS7#tFTN1EeN4rqJx z-7Nc}@F|yHfhNuQ}>}JrfmuDu`}H`#*}X;Xo{_In|;a0NCqJz+uR- zvnxJ65z3BW(M;<T}@zU-b&f!)_IO(b^`bL`4utLFB+r`8gzx9)2(>DWCq8ev%Ze72Tiz+Lk zzrVSj81*Orq|y^s39K5D)-b>BNLB~q>{?n|$3LNg^u5jJU6kX_(zi#0p zIK(uUN&o8xx_ZgXA-l$eF`+wnd<&kKR0#NJ6NxLEV`co}FLotE;0qu?HyIaUcZztb z>?m!`?!o~j*y5!&gU3;{yG#$$7J_I8a9A*nD9j{Mt^fhdxz^Kp-_9q72(Kw*v@%N* zN^=gOZUNJucI1mRX~G4j9v`7(V0zk1z-ns>D?Ll8@-dTz%A>k~@p4x9D!}JHigYh6 zFq7pyEF=B#B@%Y^L`BdDh)}z6S0&yA6PlcxY(1is^t^c!)b%2-X(0Emrge$R6~xo9 zn1}g!HwF?0N?Xis10i}g-bnIv@vBH?SM?yOLDKAkOYl=AhXLwj>Ht)!40s*%?Zs}x z`))2ZaYFy;r3*i%S4-d!EYvXk$4TRJ= ziBPf?k$M|Ev00&o;Y51(_s(X1sB`4ysV@8fM%8JbF8exkf8g4M0pa+OuNT*l`g``I z9rdaI@H=^0zA-RiLRC4`XXW82>zR*AR&TPRtt@7?sXU=bA%o#esQuv-vES5qA8%>a zz>KjReZWtvx=btUeNa`sopsLFM~0GDMNWL->r&ren?9~Vi>dY%ow&2bkd_tI4Jf)Y zn0q}36&_Bq=;fs(kPyK)Ku(#XWn%gjwO+$`q?mYbvQ*=oK5YG`tx6P&>o4q+JP!~s z{D3?TLE6&PzYBb#5i2iK_WJv`rx+_0^!)6lt;gqu1Ad({OtV&JVkr-$jX$Mrpr`v_ zYKK4Cb_9^oN}76AEdI;+`p0vZSl^{R>YGdTJ~aUjep$aX=(%mA$=*p4Jss*x;rLJj zNH60s<;;WaUN2}05;2QcuC^B~+FFWUeN;!=lne}?lfeKhijOIedtUT#NoW`JUxqe( zS+0$!Z`Aj!h|d_kY?ZZW%!@O3`yvSDyoD;>)$*O&>HAsVm$ar!o&#!BHqGx8oGE{_ zA=gdg7JgzZK<_7b+98xZ{eHFykuzc$vSJG93Mq80a^YDwk@Y7i>`uzf`IvjlJw4Qr za^AbyOsZ>wO!k7auE5DvKG7CcwEO|tyctzg-M^Wqp(5{s7XA1h{jIVr%GD+x>VJVd zb5{0oK?ixVy%P3b=oU&y!-|aNHGQ0VuBISbY7U>!oZiNyuGCON9pd3}@nea7YM&49 zdx*G1?DP<(uz0=m{Z5&M>w#jon~2N7jc<;D(gL_(Q40_5-N%*Q+@pBrr|pb_dPs!! zzbuiX1bpEpMKTaCU{v}67stA`$9{Qb$NsH4vxe79^lBd(yq2EwVEzDGqWKGKB#QG4 zhR(?~x#VVL>m{jn<%I&)LiXox{8lUOKj;@er^eD+Igi%?UIw7R~4f(c9-YfR5DEI zxOqS{9CcK7;_unPXU6>|Gm2~fNQFZ&`IJJ4Dl?|cvVMZk4|~_*2BA;nI){{-FtACl z>*>tfMe#p3KQkKNC;Z~$DNN%riaEDRvuPY63zTAm`(e_V*kbc4SGHs4nKoq<677GyMJVx-UEc5Kzcd UQvb0qIRV%e0e=$5#ZprK36TDOmH+?% delta 1706 zcmZ|HYdjMQ1IO`Uc`W2Imr9pe(<+(~W;K=Bj!lovIfQ6(8CkjHI%H-JwX|H?L6(gc zKE=o_b4|1kxm99Eh$KvpJuFfvJI{;ryzKw_`}>y}bnE93RiL#la24)^3Y2?Etxqt&oXEh#M+0NB<_#5sB- zj4k?(M~-{!R4$H2@J2~RWwaA5alvwFAL1xi7d!+UJEp35#gdroEcX<5nk!X4sHlg6 zOB^6k=bFiC4QFf{&Wyyhm&Nhyi6-5(jBli?z1Gq)S_o=zn7pwdX^j0iwLZ91v~*&t zOAlM3H)Eg0VPjFBUwB)yu_OKs`qv&%!|)bvKghl-ej5fBK!v?HGz-YJ;upz4i2ZTi?y&OWxp$ zl&?^;8swEVEB$x$Co3EvA4>s(O6xQJT70a^&;tfA<>k2*n{Hpi%qdY2991@Ckfb;P z?QWZ{gxlF3n;fOB zOkk4U%VklLTQ#yf>c7efu;IW;aA(ak;&is7B*18{kAPbpGEXaB89nk5GCuO`ElA;N zhI0Qv;Td;^=LZ?&uxIhYkCpKLJhMBSEAUr+uyXodrg*5lEkjH`psu@@%{FEQgi@*L zjZqR)b0Oc#a{%|YCjoWuys>A&TxUFULYMeOdnIkyJWtamIL^EG6S9d_MAB)6x!vKX zMI+Sm?$v@ru16yUcekuP4*y`2BTeV@)P?;T4pnd$L6UH6Po-AII_*j+VN||r7g&D# zpohz>GV%Gl1;X}$(cl<&@lzYmrrzmkuaQRYj==tutmbczMuZoyZ;$xBYm(2TNc&3z z6dU_X3MSMFamvj@8)6f~_NA`sMEhVbx78T`W?ZTh{CeV!4cM^`&$x)Q1+t8gMB!NG z%GW5g-?ibMhe09TZsh(u%@FU(slUuOD28i|ey@!?^~Rr7H!9P6av5JT{ZavizO|66 zk@_xg2XkV+Klc*K$8wue=7X5Yv5)g*YJ~!xIV}OH(5AW!Zk7G_wT>uW&i4`Ogk`zv zv=l`8u~vt}iIGc53|r~SzGEl9s$XIxR zx%SmVhCdiDHY1%72~}deQc^k9bjy919|1&p`Mvgr=40aiTy0C2)66gv_BordT8j4K zr&Y;-#U9r1@?mx(XvHdMKen$1|TSrX$i~DV%;uoM_3Ldcjfys+;v^Csxx%!yKZQ^ z8cfi972Q_B%n&oHP0RIcjC_JjH9(~`c(nT7-|s^-{UyfL4A!}+U?ad_xG})47}(AF ze11P{$Eu^Ks9ldDaLA@Bu@g=f^{!QO^E2hwKD0rw(O0ynM+3~P=}(OMwjG&#aYVu6 zoL(M!lY=qAiKjdi;!)um$h;D(G%px#N zu)Mm0-FlI4Fpkg1(Hqu1>&-;1RxP7x3 zta<_Sj~(mPprTD$*p}nJt#n=$&@mL`cM4xx8SNQxfATPSzQgN&$K^LS5c=sevNK+? zp@o03;5nn4J3E}AC9t(#=vujZ9|=xBkTu=ww*(fE$$_PE!mC4d1kLDn#LcHCHP7B_ zJe9cp@&X|kWcdl};rHkwqoJlC%v4$>IOP+lVSzJ*nIh_Q#y{T$-dZq5ck^T%^QV;o zmc1fPgnkL5?&-@3ZL+9_7vZBXckXPR#ZwZF>f2#N6)#y#ro(a`(3ihu(wSe!+_n>- WHke7PLS<6{{~Hlc!c}Aa)BXnj*dPx8 diff --git a/packages/SystemUI/res/drawable-nodpi/halo_speech_r_u.9.png b/packages/SystemUI/res/drawable-nodpi/halo_speech_r_u.9.png index 8b54e04fb94c16a1c63206aa6b53cab05f87111a..e58bb2f79f003653cfaf3726518bf90a508d0255 100755 GIT binary patch delta 1907 zcmaiucU;m51I7WhM03EYgheW@)KCEdaTMSWXG9sU+$%N3QO?VN&@Ro9=g1s+<(+Bj zCS*MlKqr!QiF7;`tB=KzX;hjX z5w8#ElSnkQ;sJTE@t?Y;R5F2#C6IMV1QHfY$5ZJhbO4W|9#{l@fQUcnrePrR3jfCR z{~MO}9gI!;9ipQ^ApXxUX=@Oa!vFc3h7mI1M*HRDfIx?6766qMIlSn|4!CG@v|)CX zGhP|CG#I$hcGPiKG!CVS91(b`nWDvEuttLE^zC@pRg<4Qj7!6pXQ~;KrS$)U0^WE8fEm0T?0y7n`>b4dxk9 zz!aSuc8`a&k=0VV!olD}1uHCzl;#;{m)-7}ILli2x)Me%QdU{)4q%&p`S|ND&PG*S z2ml0}ceCNp-;Q{&ccT$XgB2XEPh_-mO^loOODdu05=}~Ol1CW|y|OPsmR~93H1k>V=dLnUG45aVaZVp@ z36>QH)et2259SZ&&c^fqu9Ee?7=_RptG0N53cVy5EN?*1QVe0*L&mtZK=z-yFzAJu zKIBq1a6tB>h-`_W@OQP=#h{wPt>sARvk8l#qEeuvSeniQ2?bv zn<6pCrRA-=@*U5T2UZ$obG)=~Fhlpc} zedFpL^f=vJAIUBGZqz&qQ?C8j&W_oLX{R``DMyuOJ?|6p&ep_+hp@UEx&LzZga$JKP@GcweXLUDk zcv$z2I2!L3a_68Wp@)3B9!njbVKrtK&-twk#b-|5T&DE)>O3uW>TY^g(9s~T-YMn}OW|8AuHlXLUwaHfno5jnYeFVAi<7jb zGRI593fENg@h7Df;6uSph`wpWSdC(*Fr@i!T+-g7LX5qjo{r#*yG#b0X>DDmv?8e< zO@nS*-8J*qzAt8K4sS2=im!pB6!nnMbj*~be23l%M-!!%N{{(Z3Q~fI2P#!Thg1A- zE5*lhQ=Z*Bnzvo#UY$Q&wDsJ%in+XRjla6C!ZOSn8pyJ{s_KqoctwYOEsJ`ha^JN( zOIzWLZS;>|JnJ9vId_k34o5BgriL0kyv?cIuF{^g)09mk!jE*bCq~lyBj%-wmW4MU zrmEYY)sNWW0->dDqgEefMb64T&*i)+_;zuR8*Z|6h8LLcuNK~ux%xd4&G;k9JhorU zsl!!!dceTx`!@6N5j&>BFIUWRBV*FKey~*frmR~AhhM_{*$u-a-SZ(+3u71KNe*yU z!o$2<&UcMGp|kf{ZT^KLmIjg>JZeqNil1#L(wT8-yXDxafVYV98sbu)7(qAI` zTg#tm2l=|!JCG(r9l8E0yC`mf=C~KrP>^_<9Ju;?Vz{r`3>{3Z1hub=hLuieSPe>S zc1f-);U=|s{;48wC!-wp6p>ysJ=_NX>`}R3&ubI)@pU1H`7&vXs=Hi2p=X9e&><>at4-U!00&pR>N*(z@@ z3zVUCxSrgTZsDgK$+U!4`$ZWE31QpmFXW_DK@~3Ivcg@&0@kCH-&7zP<%rCXRLU?-09=xUZ!)BrkJ^RLj>1djA&>^&oQftLbG9;nDBh?Y8)X0= wZ_&dvzX`*2zTaB_+eE-s61yf7HTT7JLD6;I*k;%GUeJLo=;wf^G&lag04iKtU;qFB delta 1692 zcmZ|GeLNEg1Hkbad4D=ay|usbB;dQ29PGvs1oUgx}A$MbwX_x#)M@9(cjTL3D=$w8iZn#-|%mxHk4<;biK zAdE!^8iMWMaJ#c8G~C|a9f5GSMPlp`C^*&@jzuFJkqDLx5Nz}h!F+|FSqngT(Aj^G zS_`W>jI%AT(gdhi#+}R7xk5wbzL6Am{))L8UQ%*42MPe z(>|;O1tl7|YrD3Jli3rUAx;HaJY4lijrXXU#eI!qelKKt8Gv?U6L204kgI!BvFVF^ zpL}uEMdm(Jp=}O)*@xomYZF(t5KaG-lQ)$ zQHEDko>{5s$7L}zmj4)JDSSVoYYMyNAw<|@GV0LMQoh8a&ZjlKRxAnNny7D zAj`t0Zm2z@KWG4@2m%Dg zXU8@&5>uKbrHZ~%k3JEpq#3>fJ-0CcC)ucN$$Ma%MJKvgB_k9)j~yB4JF70M=mj-4 zZVSR6zVV|W=&jVF*swk8c^UJS<;*R=woFeUmxoXINJgfqBeEpuqzTRAn*{n%5fnv= z2dZ`|DO4xUj)frv!Y1nq_x#YFDV_$7Q4&+EAFS9V>V4`Jhq@ZBllM@&_-ujUct@Yh zjp$X%`MPVGYatjb6Mw9xZ%Xn?&0+v?UkWh=sW|ExI0eh775#JbIrqHZ+ETs1BcS26 zmWPvMPF+Jy8&&352SY;Z)hffS4=%JzCb^lD95e8+bwlmP=97Dt&?Buj$H0sZ-(eZF1~#VQB^P{@#?UETpM%Fnw)qeJcl(GkwZCCeS4Amu6nvUaga)fTiJbO~x6w z8#VA>6mIN);BDuL?Qojys=*1U9O@=r84S&?w?!Ty;OLjm}*9fSX-8I9pZDv?T+>?5<-<^zV*Gp zlP=6B_lT)h!lj7sw9hNgpYF(`+Y1}lFq$sy=t z+pSeuzSa!N)0bpPFG%+(B)uGa%8M$vg6vT%31`-R3c$oZ_v8F;d1J<-e3Y@C`faI5#+DC%+laeb<+j6=+%pp?=T`@ck0Yd+B(1^F>jzzULW`;IYd`>3@#h_0P1z-B%##y* z^UkNYJffASMp9-hH)-~Lmggd(9Dn^%ZBvO1y-N#bO}=HUeVER!1iB&K`E2TU5dO|i zeYLEL-;JOfkGd)Q;T~-?P=#Tpse6Yxyt=Y=+7yQ}GjFU|Thu5P%))AHPC>+v12gk@ z^p!Z}NL|~}AyaSL0fS?SA_71_Qttb5(qrib<;QNLH^8>xYQA$)Z^@|1fL#XJtzfz` zCoo!WpRpe0bf|dF@-=&lU=ZL)_Nk)|jczA8Wc&*>T+*%Ctjxv#8$9(udf7EOmb4i0 z<*3Soq6v%qi9iCZll{ii5R;d(rgeo7M5>W`j6hGGSGys#&hK`l1aP0*{-C>~ O{uj=jfPIP%%lt2td=ps! diff --git a/packages/SystemUI/res/layout/halo_speech.xml b/packages/SystemUI/res/layout/halo_speech.xml index 0a89c52e920..5789ccc8b24 100644 --- a/packages/SystemUI/res/layout/halo_speech.xml +++ b/packages/SystemUI/res/layout/halo_speech.xml @@ -36,7 +36,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" - android:padding="5dp" + android:paddingLeft="5dp" + android:paddingRight="5dp" android:textColor="#ffffff" android:fontFamily="sans-serif-light" android:textSize="@dimen/halo_speech_text_size" diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index de83a863cb9..69070999998 100755 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -300,7 +300,7 @@ 24dp 16dp 14sp - 18sp + 16sp 4dp 13dp 3dp diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 2105010998d..dceecdcfef1 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -670,10 +670,10 @@ Dismiss notification Hide - Clear all notifications - Hide and silence until woken + Dismiss all notifications + Hide & silence until woken This is HALO Move me: 2x-tap & drag - Horizontal drag to task + Browse tasks: Horizontal drag diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 22c4857f38a..29ed3849339 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -308,9 +308,6 @@ public void onChange(boolean selfChange) { private RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() { @Override public boolean onClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) { - - android.util.Log.d("PARANOID", "Notification click handler invoked for intent: " + pendingIntent); - if (DEBUG) { Slog.v(TAG, "Notification click handler invoked for intent: " + pendingIntent); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index 3a9646c0ee3..092a44a364e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -1091,7 +1091,7 @@ public void ticker(String tickerText, int delay, int startDuration) { return; } - setHaloContentHeight((int)(mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height) * 0.7f)); + setHaloContentHeight((int)(mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height) * 0.6f)); mHaloTickerContent.setVisibility(View.GONE); mHaloTextView.setVisibility(View.VISIBLE); mHaloTextView.setText(tickerText); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java index 035f1ecf3cc..d6b993d6561 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java @@ -207,8 +207,8 @@ public void setHaloSize(float fraction) { mHaloCount.setLayoutParams(layoutParams2); mHaloCount.setTextSize(TypedValue.COMPLEX_UNIT_PX, newNumberTextSize); - final int newSpeechTextSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_text_size) * fraction); - mHaloTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSpeechTextSize); + //final int newSpeechTextSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_text_size) * fraction); + //mHaloTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSpeechTextSize); final int newBatchIconSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_icon_size) * fraction); RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(newBatchIconSize, newBatchIconSize); From 1e4a172bd2873cf4f00a7a347c95b942f6e585eb Mon Sep 17 00:00:00 2001 From: Anu6is Date: Sun, 18 Aug 2013 17:29:46 -0500 Subject: [PATCH 21/31] fix HALO silence bug when notification is dismissed --- .../SystemUI/src/com/android/systemui/statusbar/halo/Halo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index 092a44a364e..e2c92358fc0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -1571,7 +1571,7 @@ public void run() { } final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); mEffect.setHaloMessageNumber(c); - if (mState != State.HIDDEN) { + if (mState == State.IDLE) { mEffect.nap(1500); if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); } From 5cb8b2ec7f91f7870f595c96ecb788702e840889 Mon Sep 17 00:00:00 2001 From: drcmda Date: Mon, 19 Aug 2013 17:55:54 +0100 Subject: [PATCH 22/31] halo, wrong touch calculation, nap trigger fixed Change-Id: Ib09163d71cddb2cbe8f375313e0c1e03b37fd504 --- .../android/systemui/statusbar/halo/Halo.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index e2c92358fc0..332c243a5bf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -369,6 +369,12 @@ private void initControl() { // Get actual screen size mScreenWidth = mEffect.getWidth(); mScreenHeight = mEffect.getHeight(); + + mKillX = mScreenWidth / 2; + mKillY = mIconHalfSize; + + // In the unlikely event the user still holds on to HALO just let it be + if (mState != State.IDLE) return; // Halo dock position preferences = mContext.getSharedPreferences("Halo", 0); @@ -380,9 +386,6 @@ private void initControl() { preferences.edit().putBoolean(KEY_HALO_FIRST_RUN, false).apply(); } - mKillX = mScreenWidth / 2; - mKillY = mIconHalfSize; - if (!mFirstStart) { if (msavePositionY < 0) mEffect.setHaloY(0); float mTmpHaloY = (float) msavePositionY / mScreenWidth * (mScreenHeight); @@ -595,11 +598,10 @@ private boolean verticalGesture() { @Override public boolean onTouchEvent(MotionEvent event) { - mEffect.onTouchEvent(event); - // Prevent any kind of interaction while HALO explains itself if (mState == State.FIRST_RUN) return true; + mEffect.onTouchEvent(event); mGestureDetector.onTouchEvent(event); final int action = event.getAction(); @@ -997,6 +999,9 @@ void getRawPoint(MotionEvent ev, int index, PointF point){ final int location[] = { 0, 0 }; mRoot.getLocationOnScreen(location); + final int location_effect[] = { 0, 0 }; + getLocationOnScreen(location_effect); + float x=ev.getX(index); float y=ev.getY(index); @@ -1008,12 +1013,12 @@ void getRawPoint(MotionEvent ev, int index, PointF point){ x=(float)(length*Math.cos(Math.toRadians(angle)))+location[0]; y=(float)(length*Math.sin(Math.toRadians(angle)))+location[1]; - point.set((int)x,(int)y); + point.set((int)x,(int)y - location_effect[1]); } boolean browseView(PointF loc, Rect parent, View v) { int posX = (int)loc.x; - int posY = (int)loc.y - mIconHalfSize / 2; + int posY = (int)loc.y; // - mIconHalfSize / 2; if (v instanceof ViewGroup) { ViewGroup vg = (ViewGroup)v; From a93ae1abeb2fdb4d13731815e11e0fe5d4c44891 Mon Sep 17 00:00:00 2001 From: drcmda Date: Mon, 19 Aug 2013 21:30:27 +0100 Subject: [PATCH 23/31] halo, still wrong multitouchhandling Change-Id: Id9c00c25add4a493309f170eb97acf0a06c378d0 --- .../src/com/android/systemui/statusbar/halo/Halo.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index 332c243a5bf..f0902414b6f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -1050,15 +1050,15 @@ boolean browseView(PointF loc, Rect parent, View v) { @Override public boolean onTouchEvent(MotionEvent event) { + int index = event.getActionIndex(); if (event.getActionMasked() == MotionEvent.ACTION_POINTER_UP - && event.getActionIndex() == 1 ) { - + && index != 0 ) { if (mCurrentNotficationEntry != null && mCurrentNotficationEntry.haloContent != null) { Rect rootRect = new Rect(); mHaloTickerContent.getHitRect(rootRect); PointF point = new PointF(); - getRawPoint(event, 1, point); + getRawPoint(event, index, point); browseView(point, rootRect, mCurrentNotficationEntry.haloContent); } } From cdaac81013dc3aa749105476a5a32a740a9f7445 Mon Sep 17 00:00:00 2001 From: drcmda Date: Mon, 19 Aug 2013 22:12:08 +0100 Subject: [PATCH 24/31] halo, fancy flip Change-Id: I364e63c1ad15caf8ed469a49862a533044583855 --- .../src/com/android/systemui/statusbar/halo/Halo.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index f0902414b6f..5fe21180fbc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -1229,6 +1229,7 @@ public void unscheduleSleep() { } CustomObjectAnimator contentYAnimator = new CustomObjectAnimator(this); + CustomObjectAnimator contentFlipAnimator = new CustomObjectAnimator(this); int tickerX, tickerY; @@ -1314,6 +1315,9 @@ protected void onDraw(Canvas canvas) { ? HaloProperties.ContentStyle.CONTENT_DOWN : HaloProperties.ContentStyle.CONTENT_UP); contentYAnimator.animate(ObjectAnimator.ofInt(this, "HaloContentY", y).setDuration(300), new DecelerateInterpolator(), null); + contentFlipAnimator.animate(ObjectAnimator.ofFloat(mHaloTickerWrapper, "rotationY", + mTickerLeft ? -180 : 180, 0).setDuration(300), + new DecelerateInterpolator(), null); } } From 81c6b6e191cd0f055d97f094b5af19ca196f65b8 Mon Sep 17 00:00:00 2001 From: drcmda Date: Tue, 20 Aug 2013 12:09:23 +0100 Subject: [PATCH 25/31] halo, flip for incoming messages Change-Id: If54cbd39eb926f6f78db04608ba72c3ff0c356fc --- .../statusbar/halo/CustomObjectAnimator.java | 6 ++- .../android/systemui/statusbar/halo/Halo.java | 51 ++++++++++++------- .../statusbar/halo/HaloProperties.java | 2 +- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java index 3e3e28f96b3..55c632dc539 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java @@ -29,13 +29,14 @@ public class CustomObjectAnimator { private View rootView; private Handler handler = new Handler(); private ObjectAnimator animator; + private boolean delayed = false; public CustomObjectAnimator(View root) { rootView = root; } public boolean isRunning() { - return animator != null && animator.isRunning(); + return animator != null && (animator.isRunning() || delayed); } public void animate(ObjectAnimator newInstance, TimeInterpolator interpolator, AnimatorUpdateListener update) { @@ -45,9 +46,11 @@ public void animate(ObjectAnimator newInstance, TimeInterpolator interpolator, A public void animate(final ObjectAnimator newInstance, final TimeInterpolator interpolator, final AnimatorUpdateListener update, long startDelay, final Runnable executeAfter) { + delayed = true; handler.postDelayed(new Runnable() { public void run() { runAnimation(newInstance, interpolator, update, executeAfter); + delayed = false; }}, startDelay); } @@ -94,5 +97,6 @@ public void onAnimationUpdate(ValueAnimator animation) { public void cancel(boolean unschedule) { if (unschedule) handler.removeCallbacksAndMessages(null); if (animator != null) animator.cancel(); + delayed = false; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index 5fe21180fbc..34611e92600 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -489,7 +489,7 @@ private void loadLastNotification(boolean includeCurrentDismissable) { mNotificationText = mLastNotificationEntry.notification.notification.tickerText.toString(); } - tick(mLastNotificationEntry, 0, 0, false, false); + tick(mLastNotificationEntry, 0, 0, false, false, false); } else { clearTicker(); } @@ -895,11 +895,11 @@ public boolean onTouchEvent(MotionEvent event) { if (iconIndex == -1 && !verticalGesture() && oldGesture == Gesture.TASK) { mTaskIntent = null; resetIcons(); - tick(mLastNotificationEntry, 0, -1, false, true); + tick(mLastNotificationEntry, 0, -1, false, true, false); } else { setIcon(iconIndex); NotificationData.Entry entry = mNotificationData.get(iconIndex); - tick(entry, 0, -1, false, true); + tick(entry, 0, -1, false, true, false); mTaskIntent = entry.getFloatingIntent(); } } catch (Exception e) { @@ -1086,6 +1086,7 @@ protected void onLayout (boolean changed, int left, int top, int right, int bott } public void killTicker() { + flipContent(0, 0); tickerAnimator.animate(ObjectAnimator.ofFloat(this, "haloContentAlpha", 0f).setDuration(250), new DecelerateInterpolator(), null); } @@ -1096,6 +1097,7 @@ public void ticker(String tickerText, int delay, int startDuration) { return; } + flipContent(0, 0); setHaloContentHeight((int)(mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height) * 0.6f)); mHaloTickerContent.setVisibility(View.GONE); mHaloTextView.setVisibility(View.VISIBLE); @@ -1112,7 +1114,7 @@ public void ticker(String tickerText, int delay, int startDuration) { new DecelerateInterpolator(), null, delay, null); } - public void ticker(int delay, int startDuration) { + public void ticker(int delay, int startDuration, boolean flip) { setHaloContentHeight(mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height)); mHaloTickerContent.setVisibility(View.VISIBLE); @@ -1134,6 +1136,7 @@ public void ticker(int delay, int startDuration) { tickerAnimator.animate(ObjectAnimator.ofFloat(this, "haloContentAlpha", 1f).setDuration(250), new DecelerateInterpolator(), null, delay, null); } + if (flip) flipContent(500, delay); } public void ping(final Paint paint, final long delay) { @@ -1229,7 +1232,20 @@ public void unscheduleSleep() { } CustomObjectAnimator contentYAnimator = new CustomObjectAnimator(this); - CustomObjectAnimator contentFlipAnimator = new CustomObjectAnimator(this); + public void slideContent(int duration, int y) { + contentYAnimator.animate(ObjectAnimator.ofInt(this, "HaloContentY", y).setDuration(duration), + new DecelerateInterpolator(), null); + } + + CustomObjectAnimator contentFlipAnimator = new CustomObjectAnimator(this); + public void flipContent(int duration, int delay) { + + // Make sure the animation does not stutter by letting it finish + if (contentFlipAnimator.isRunning()) return; + + contentFlipAnimator.animate(ObjectAnimator.ofFloat(mHaloTickerWrapper, "rotationY", + mTickerLeft ? -180 : 180, 0).setDuration(duration), new DecelerateInterpolator(), null, delay, null); + } int tickerX, tickerY; @@ -1310,14 +1326,15 @@ protected void onDraw(Canvas canvas) { if (mState == State.DRAG) { setHaloContentY(y); } else { - if (y != getHaloContentY() && !contentYAnimator.isRunning()) { + // Move content when ... + // 1. the calculated Y position is off + // 2. the content-animator is not running or we're in tasking state + if (y != getHaloContentY() && (!contentYAnimator.isRunning() || verticalGesture())) { setHaloContentBackground(mTickerLeft, mGesture == Gesture.TASK && mHaloY > mIconHalfSize ? HaloProperties.ContentStyle.CONTENT_DOWN : HaloProperties.ContentStyle.CONTENT_UP); - contentYAnimator.animate(ObjectAnimator.ofInt(this, "HaloContentY", y).setDuration(300), - new DecelerateInterpolator(), null); - contentFlipAnimator.animate(ObjectAnimator.ofFloat(mHaloTickerWrapper, "rotationY", - mTickerLeft ? -180 : 180, 0).setDuration(300), - new DecelerateInterpolator(), null); + int duration = !verticalGesture() ? 300 : 0; + slideContent(duration, y); + flipContent(duration, 0); } } @@ -1378,7 +1395,7 @@ void clearTicker() { mEffect.invalidate(); } - void tick(NotificationData.Entry entry, int delay, int duration, boolean alwaysFlip, boolean showContent) { + void tick(NotificationData.Entry entry, int delay, int duration, boolean alwaysFlip, boolean showContent, boolean flipContent) { if (entry == null) { clearTicker(); return; @@ -1399,13 +1416,13 @@ void tick(NotificationData.Entry entry, int delay, int duration, boolean alwaysF try { ((ViewGroup)mEffect.mHaloTickerContent).removeAllViews(); ((ViewGroup)mEffect.mHaloTickerContent).addView(entry.haloContent); - mEffect.ticker(delay, duration); + mEffect.ticker(delay, duration, flipContent); } catch(Exception e) { // haloContent had a view already? Let's give it one last chance ... try { mBar.prepareHaloNotification(entry, notification, false); if (entry.haloContent != null) ((ViewGroup)mEffect.mHaloTickerContent).addView(entry.haloContent); - mEffect.ticker(delay, duration); + mEffect.ticker(delay, duration, flipContent); } catch(Exception ex) { // Screw it, we're going with a simple text mEffect.ticker(mNotificationText, delay, duration); @@ -1469,7 +1486,7 @@ public void updateTicker(StatusBarNotification notification, String text) { if (mHideTicker) mEffect.sleep(HaloEffect.SLEEP_DELAY + HaloEffect.WAKE_TIME * 2, HaloEffect.SLEEP_TIME, false); } - tick(entry, HaloEffect.WAKE_TIME * 2, 1000, true, true); + tick(entry, HaloEffect.WAKE_TIME * 2, 1000, true, true, true); // Pop while not tasking, only if notification is certified fresh if (mGesture != Gesture.TASK && mState != State.SILENT) mEffect.ping(mPaintHoloBlue, HaloEffect.WAKE_TIME * 2); @@ -1576,7 +1593,7 @@ public void run() { if (entry == null && getHaloMsgCount() > 0) { loadLastNotification(false); } else { - tick(entry, 0, 0, false, false); + tick(entry, 0, 0, false, false, false); } final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); mEffect.setHaloMessageNumber(c); @@ -1611,7 +1628,7 @@ public void run() { mEffect.wake(); mEffect.nap(HaloEffect.NAP_DELAY + HaloEffect.WAKE_TIME * 2); if (mHideTicker) mEffect.sleep(HaloEffect.SLEEP_DELAY + HaloEffect.WAKE_TIME * 2, HaloEffect.SLEEP_TIME, false); - tick(entry, HaloEffect.WAKE_TIME * 2, 1000, false, true); + tick(entry, HaloEffect.WAKE_TIME * 2, 1000, false, true, true); mEffect.ping(mPaintHoloBlue, HaloEffect.WAKE_TIME * 2); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java index d6b993d6561..362b0e1db85 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java @@ -374,7 +374,7 @@ public void setHaloOverlay(Overlay overlay, float overlayAlpha) { private ContentStyle mLastContentStyle = ContentStyle.CONTENT_NONE; public void setHaloContentBackground(boolean contentLeft, ContentStyle style) { - if (style != mLastContentStyle) { + if (contentLeft != mLastContentStateLeft || style != mLastContentStyle) { // Set background switch(style) { case CONTENT_UP: From 71bae6ac2cc9390ae4b4257f203cd950c6c95b43 Mon Sep 17 00:00:00 2001 From: drcmda Date: Tue, 20 Aug 2013 17:16:42 +0100 Subject: [PATCH 26/31] halo performance, batch revamp Change-Id: Ic32c146a1e4753c5a3342831d6c719a654816e54 --- .../res/drawable/halo_count_shape.xml | 8 --- packages/SystemUI/res/layout/halo_number.xml | 44 +++------------- .../statusbar/halo/CustomObjectAnimator.java | 2 +- .../android/systemui/statusbar/halo/Halo.java | 9 ++-- .../statusbar/halo/HaloProperties.java | 51 +++++++++---------- 5 files changed, 37 insertions(+), 77 deletions(-) delete mode 100644 packages/SystemUI/res/drawable/halo_count_shape.xml diff --git a/packages/SystemUI/res/drawable/halo_count_shape.xml b/packages/SystemUI/res/drawable/halo_count_shape.xml deleted file mode 100644 index b83aec5f22f..00000000000 --- a/packages/SystemUI/res/drawable/halo_count_shape.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/packages/SystemUI/res/layout/halo_number.xml b/packages/SystemUI/res/layout/halo_number.xml index 3078c6bd011..f0b03b8349e 100644 --- a/packages/SystemUI/res/layout/halo_number.xml +++ b/packages/SystemUI/res/layout/halo_number.xml @@ -20,51 +20,23 @@ + android:layout_width="@dimen/halo_number_size" + android:layout_height="@dimen/halo_number_size" + android:background="@drawable/halo_number_shape"> - - - - - - diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java index 55c632dc539..0152af50361 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java @@ -69,7 +69,7 @@ private void runAnimation(ObjectAnimator newInstance, TimeInterpolator interpola @Override public void onAnimationUpdate(ValueAnimator animation) { final float value = animation.getAnimatedFraction(); - if (value != oldValue) rootView.invalidate(); + if (value != oldValue) rootView.postInvalidate(); oldValue = value; }}); } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index 34611e92600..6db74b9b155 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -1159,7 +1159,7 @@ public void run() { public void onAnimationUpdate(ValueAnimator animation) { pingRadius = (int)((pingMaxRadius - pingMinRadius) * animation.getAnimatedFraction()) + pingMinRadius; - invalidate(); + postInvalidate(); }}); // prevent ping spam @@ -1259,7 +1259,6 @@ protected void onDraw(Canvas canvas) { } // Content - state = canvas.save(); final int tickerHeight = mHaloTickerWrapper.getMeasuredHeight(); int ch = mGesture == Gesture.TASK ? 0 : tickerHeight / 2; int cw = mHaloTickerWrapper.getMeasuredWidth(); @@ -1353,6 +1352,7 @@ protected void onDraw(Canvas canvas) { mHaloBubble.draw(canvas); canvas.restoreToCount(state); + // Number if (mState == State.IDLE || mState == State.GESTURES) { state = canvas.save(); @@ -1384,9 +1384,6 @@ void clearTicker() { mEffect.msgNumberFlipAnimator.cancel(true); mEffect.tickerAnimator.cancel(true); mEffect.mHaloNumber.setAlpha(0f); - mEffect.mHaloCount.setAlpha(0f); - mEffect.mHaloPinned.setAlpha(0f); - mEffect.mHaloSystemIcon.setAlpha(0f); mEffect.mHaloNumberIcon.setAlpha(0f); mContentIntent = null; mCurrentNotficationEntry = null; @@ -1438,7 +1435,7 @@ void tick(NotificationData.Entry entry, int delay, int duration, boolean alwaysF if (entry.notification.getPackageName().equals("com.paranoid.halo")) { msgType = HaloProperties.MessageType.PINNED; } else if (!entry.notification.isClearable()) { - msgType = HaloProperties.MessageType.SYSTEM; + msgType = HaloProperties.MessageType.PINNED; } else { msgType = HaloProperties.MessageType.MESSAGE; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java index 362b0e1db85..52e478d5f89 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java @@ -87,6 +87,9 @@ public enum MessageType { private Drawable mHaloSilenceR; private Drawable mHaloMessage; private Drawable mHaloCurrentOverlay; + private Drawable mHaloIconMessage; + private Drawable mHaloIconPersistent; + private Drawable mHaloIconPinned; protected Drawable mHaloSpeechL, mHaloSpeechR, mHaloSpeechLD, mHaloSpeechRD; @@ -97,8 +100,8 @@ public enum MessageType { protected TextView mHaloTextView; protected View mHaloNumberView; - protected TextView mHaloNumber, mHaloCount; - protected ImageView mHaloNumberIcon, mHaloSystemIcon, mHaloPinned; + protected TextView mHaloNumber; + protected ImageView mHaloNumberIcon; protected RelativeLayout mHaloNumberContainer; private boolean mEnableColor; @@ -134,6 +137,10 @@ public HaloProperties(Context context) { mHaloSpeechLD = mContext.getResources().getDrawable(R.drawable.halo_speech_l_d); mHaloSpeechRD = mContext.getResources().getDrawable(R.drawable.halo_speech_r_d); + mHaloIconMessage = mContext.getResources().getDrawable(R.drawable.halo_batch_message); + mHaloIconPersistent = mContext.getResources().getDrawable(R.drawable.halo_system_message); + mHaloIconPinned = mContext.getResources().getDrawable(R.drawable.halo_pinned_app); + mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mHaloBubble = mInflater.inflate(R.layout.halo_bubble, null); @@ -151,13 +158,8 @@ public HaloProperties(Context context) { mHaloNumberView = mInflater.inflate(R.layout.halo_number, null); mHaloNumberContainer = (RelativeLayout)mHaloNumberView.findViewById(R.id.container); mHaloNumber = (TextView) mHaloNumberView.findViewById(R.id.number); - mHaloCount = (TextView) mHaloNumberView.findViewById(R.id.haloCount); mHaloNumberIcon = (ImageView) mHaloNumberView.findViewById(R.id.icon); - mHaloNumberIcon.setImageDrawable(mContext.getResources().getDrawable(R.drawable.halo_batch_message)); - mHaloSystemIcon = (ImageView) mHaloNumberView.findViewById(R.id.system); - mHaloSystemIcon.setImageDrawable(mContext.getResources().getDrawable(R.drawable.halo_system_message)); - mHaloPinned = (ImageView) mHaloNumberView.findViewById(R.id.pinned); - mHaloPinned.setImageDrawable(mContext.getResources().getDrawable(R.drawable.halo_pinned_app)); + mHaloNumberIcon.setImageDrawable(mHaloIconMessage); mHaloContentHeight = mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height); @@ -204,8 +206,6 @@ public void setHaloSize(float fraction) { RelativeLayout.LayoutParams layoutParams2 = new RelativeLayout.LayoutParams(newNumberSize, newNumberSize); mHaloNumber.setLayoutParams(layoutParams2); mHaloNumber.setTextSize(TypedValue.COMPLEX_UNIT_PX, newNumberTextSize); - mHaloCount.setLayoutParams(layoutParams2); - mHaloCount.setTextSize(TypedValue.COMPLEX_UNIT_PX, newNumberTextSize); //final int newSpeechTextSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_text_size) * fraction); //mHaloTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSpeechTextSize); @@ -215,8 +215,6 @@ public void setHaloSize(float fraction) { layoutParams3.addRule(RelativeLayout.CENTER_VERTICAL); layoutParams3.addRule(RelativeLayout.CENTER_HORIZONTAL); mHaloNumberIcon.setLayoutParams(layoutParams3); - mHaloSystemIcon.setLayoutParams(layoutParams3); - mHaloPinned.setLayoutParams(layoutParams3); updateResources(mLastContentStateLeft); } @@ -261,30 +259,30 @@ public void run() { msgNumberAlphaAnimator.cancel(true); float oldAlpha = mHaloNumberContainer.getAlpha(); + mHaloNumberContainer.getBackground().clearColorFilter(); mHaloNumberContainer.setAlpha(1f); - mHaloNumber.setAlpha(1f); - mHaloCount.setAlpha(0f); - mHaloCount.setText(""); + mHaloNumber.setAlpha(0f); mHaloNumberIcon.setAlpha(0f); - mHaloSystemIcon.setAlpha(0f); - mHaloPinned.setAlpha(0f); + if (msgCount > 0) { - mHaloNumber.setAlpha(0f); - mHaloCount.setText(String.valueOf(msgCount)); - mHaloCount.setAlpha(1f); + mHaloNumberContainer.getBackground().setColorFilter(0xff4fa736, PorterDuff.Mode.SRC_IN); + mHaloNumber.setText(String.valueOf(msgCount)); + mHaloNumber.setAlpha(1f); } else if (value < 1 && msgCount < 1) { - mHaloNumber.setText(""); if (msgType == MessageType.PINNED) { - mHaloPinned.setAlpha(1f); + mHaloNumberIcon.setImageDrawable(mHaloIconPinned); } else if (msgType == MessageType.SYSTEM) { - mHaloSystemIcon.setAlpha(1f); + mHaloNumberIcon.setImageDrawable(mHaloIconPersistent); } else { - mHaloNumberIcon.setAlpha(1f); + mHaloNumberIcon.setImageDrawable(mHaloIconMessage); } + mHaloNumberIcon.setAlpha(1f); } else if (value < 100) { mHaloNumber.setText(String.valueOf(value)); + mHaloNumber.setAlpha(1f); } else { mHaloNumber.setText("+"); + mHaloNumber.setAlpha(1f); } if (value < 1 && msgCount < 1) { @@ -305,13 +303,12 @@ public void run() { } void setHaloMessageNumber(int count) { - mHaloCount.setText(String.valueOf(count)); + mHaloNumber.setText(String.valueOf(count)); invalidate(); } public void setHaloContentAlpha(float value) { mHaloTickerWrapper.setAlpha(value); - mHaloTextView.setTextColor(mHaloTextView.getTextColors().withAlpha((int)(value * 255))); mHaloTickerWrapper.invalidate(); mHaloContentAlpha = value; mHaloTextViewL.setAlpha(value); @@ -401,6 +398,8 @@ public void setHaloContentHeight(int size) { } public void updateResources(boolean contentLeft) { + android.util.Log.d("PARANOID", "-- updateResources"); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, mHaloContentHeight); mHaloTickerWrapper.setLayoutParams(layoutParams); From 38b2841b9adc9e1c956d628d9176cd8962398018 Mon Sep 17 00:00:00 2001 From: drcmda Date: Fri, 23 Aug 2013 13:12:15 +0100 Subject: [PATCH 27/31] halo, bugfixes 1. fixed size for content 2. flip animations for tasking only 3. batch size calculations 4. not a bug but pinned and system both get the same icon for now Change-Id: I755cd4e88c909ab8b982e014d470791661a0041e --- .../android/systemui/statusbar/halo/Halo.java | 2 +- .../statusbar/halo/HaloProperties.java | 44 ++++++++----------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index 6db74b9b155..16f3d50274f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -1483,7 +1483,7 @@ public void updateTicker(StatusBarNotification notification, String text) { if (mHideTicker) mEffect.sleep(HaloEffect.SLEEP_DELAY + HaloEffect.WAKE_TIME * 2, HaloEffect.SLEEP_TIME, false); } - tick(entry, HaloEffect.WAKE_TIME * 2, 1000, true, true, true); + tick(entry, HaloEffect.WAKE_TIME * 2, 1000, true, true, false); // Pop while not tasking, only if notification is certified fresh if (mGesture != Gesture.TASK && mState != State.SILENT) mEffect.ping(mPaintHoloBlue, HaloEffect.WAKE_TIME * 2); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java index 52e478d5f89..6c00f204a1a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java @@ -201,20 +201,23 @@ public void setHaloSize(float fraction) { newPaddingVTop = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_vpadding_top) * fraction); newPaddingVBottom = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_vpadding_bottom) * fraction); - final int newNumberSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_size) * fraction); + final int newBatchSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_size) * fraction); + final int newBatchIconSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_icon_size) * fraction); final int newNumberTextSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_text_size) * fraction); - RelativeLayout.LayoutParams layoutParams2 = new RelativeLayout.LayoutParams(newNumberSize, newNumberSize); - mHaloNumber.setLayoutParams(layoutParams2); - mHaloNumber.setTextSize(TypedValue.COMPLEX_UNIT_PX, newNumberTextSize); - //final int newSpeechTextSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_text_size) * fraction); - //mHaloTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSpeechTextSize); + LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(newBatchSize, newBatchSize); + mHaloNumberContainer.setLayoutParams(layoutParams2); - final int newBatchIconSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_icon_size) * fraction); - RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(newBatchIconSize, newBatchIconSize); + RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(newBatchSize, newBatchSize); layoutParams3.addRule(RelativeLayout.CENTER_VERTICAL); layoutParams3.addRule(RelativeLayout.CENTER_HORIZONTAL); - mHaloNumberIcon.setLayoutParams(layoutParams3); + mHaloNumber.setLayoutParams(layoutParams3); + mHaloNumber.setTextSize(TypedValue.COMPLEX_UNIT_PX, newNumberTextSize); + + RelativeLayout.LayoutParams layoutParams4 = new RelativeLayout.LayoutParams(newBatchIconSize, newBatchIconSize); + layoutParams4.addRule(RelativeLayout.CENTER_VERTICAL); + layoutParams4.addRule(RelativeLayout.CENTER_HORIZONTAL); + mHaloNumberIcon.setLayoutParams(layoutParams4); updateResources(mLastContentStateLeft); } @@ -400,8 +403,14 @@ public void setHaloContentHeight(int size) { public void updateResources(boolean contentLeft) { android.util.Log.d("PARANOID", "-- updateResources"); + // Maximal stretch for speech bubble, wrap_content regular text + final boolean portrait = getWidth() < getHeight(); + final int iconSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_bubble_size) * mFraction); + int portraitWidth = portrait ? ((int)(getWidth() * 0.95f) - iconSize) : ((int)(getHeight() * 0.95f)); + if (mHaloTextView.getVisibility() == View.VISIBLE) portraitWidth = LinearLayout.LayoutParams.WRAP_CONTENT; + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, mHaloContentHeight); + portraitWidth, mHaloContentHeight); mHaloTickerWrapper.setLayoutParams(layoutParams); // Set background and override its padding @@ -420,21 +429,6 @@ public void updateResources(boolean contentLeft) { MeasureSpec.getSize(mHaloNumberView.getMeasuredHeight())); mHaloNumberView.layout(0, 0, 0, 0); - // Maximal stretch for speech bubble - final int iconSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_bubble_size) * mFraction); - final int maximumWidth = (int)(getWidth() * 0.95f) - iconSize; - - if (mHaloTickerWrapper.getMeasuredWidth() > maximumWidth) { - final int optimalWidth = iconSize * 5; - final int newSize = maximumWidth > optimalWidth ? optimalWidth : maximumWidth; - layoutParams = new LinearLayout.LayoutParams(newSize, mHaloContentHeight); - mHaloTickerWrapper.setLayoutParams(layoutParams); - - mHaloContentView.measure(MeasureSpec.getSize(mHaloContentView.getMeasuredWidth()), - MeasureSpec.getSize(mHaloContentView.getMeasuredHeight())); - mHaloContentView.layout(0, 0, 0, 0); - } - mLastContentStateLeft = contentLeft; } From 49c57e4544e7e51799d1dc2cf55e0345e0635d67 Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Thu, 29 Aug 2013 10:10:27 +0100 Subject: [PATCH 28/31] fix xml encoding --- packages/SystemUI/res/layout/halo_bubble.xml | 2 +- packages/SystemUI/res/layout/halo_number.xml | 2 +- packages/SystemUI/res/layout/halo_speech.xml | 2 +- packages/SystemUI/res/layout/halo_trigger.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/res/layout/halo_bubble.xml b/packages/SystemUI/res/layout/halo_bubble.xml index b2a4f822fce..f1e2be091fc 100644 --- a/packages/SystemUI/res/layout/halo_bubble.xml +++ b/packages/SystemUI/res/layout/halo_bubble.xml @@ -1,3 +1,4 @@ + - - diff --git a/packages/SystemUI/res/layout/halo_speech.xml b/packages/SystemUI/res/layout/halo_speech.xml index 5789ccc8b24..4b933fedbd5 100644 --- a/packages/SystemUI/res/layout/halo_speech.xml +++ b/packages/SystemUI/res/layout/halo_speech.xml @@ -1,3 +1,4 @@ + - - Date: Thu, 29 Aug 2013 10:50:19 +0100 Subject: [PATCH 29/31] fix build issues (HALO Update) --- .../java/com/android/server/NotificationManagerService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 02af3ab2765..3b8896edb05 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -59,6 +59,9 @@ import android.os.UserHandle; import android.os.Vibrator; import android.provider.Settings; +import android.service.notification.INotificationListener; +import android.service.notification.NotificationListenerService; +import android.service.notification.StatusBarNotification; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.AtomicFile; From dd8c6473381df805495395b7a3dfc5fb3e77ccd2 Mon Sep 17 00:00:00 2001 From: Pete Osborne Date: Thu, 29 Aug 2013 11:08:46 +0100 Subject: [PATCH 30/31] revert changes made to NotificationManagerService --- .../server/NotificationManagerService.java | 430 +----------------- 1 file changed, 1 insertion(+), 429 deletions(-) diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 3b8896edb05..f01fca78ffa 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -59,9 +59,6 @@ import android.os.UserHandle; import android.os.Vibrator; import android.provider.Settings; -import android.service.notification.INotificationListener; -import android.service.notification.NotificationListenerService; -import android.service.notification.StatusBarNotification; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.AtomicFile; @@ -460,432 +457,7 @@ private static String idDebugString(Context baseContext, String packageName, int } } - /** - * System-only API for getting a list of current (i.e. not cleared) notifications. - * - * Requires ACCESS_NOTIFICATIONS which is signature|system. - */ - @Override - public StatusBarNotification[] getActiveNotifications(String callingPkg) { - // enforce() will ensure the calling uid has the correct permission - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS, - "NotificationManagerService.getActiveNotifications"); - - StatusBarNotification[] tmp = null; - int uid = Binder.getCallingUid(); - - // noteOp will check to make sure the callingPkg matches the uid - if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg) - == AppOpsManager.MODE_ALLOWED) { - synchronized (mNotificationList) { - tmp = new StatusBarNotification[mNotificationList.size()]; - final int N = mNotificationList.size(); - for (int i=0; i installedServices = pm.queryIntentServicesAsUser( - new Intent(NotificationListenerService.SERVICE_INTERFACE), - PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, - currentUser); - - Set installed = new HashSet(); - for (int i = 0, count = installedServices.size(); i < count; i++) { - ResolveInfo resolveInfo = installedServices.get(i); - ServiceInfo info = resolveInfo.serviceInfo; - - if (!android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE.equals( - info.permission)) { - Slog.w(TAG, "Skipping notification listener service " - + info.packageName + "/" + info.name - + ": it does not require the permission " - + android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE); - continue; - } - installed.add(new ComponentName(info.packageName, info.name)); - } - - String flatOut = ""; - if (!installed.isEmpty()) { - String[] enabled = flatIn.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR); - ArrayList remaining = new ArrayList(enabled.length); - for (int i = 0; i < enabled.length; i++) { - ComponentName enabledComponent = ComponentName.unflattenFromString(enabled[i]); - if (installed.contains(enabledComponent)) { - remaining.add(enabled[i]); - } - } - flatOut = TextUtils.join(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR, remaining); - } - if (DBG) Slog.v(TAG, "flat after: " + flatOut); - if (!flatIn.equals(flatOut)) { - Settings.Secure.putStringForUser(mContext.getContentResolver(), - Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, - flatOut, currentUser); - } - } - } - - /** - * Called whenever packages change, the user switches, or ENABLED_NOTIFICATION_LISTENERS - * is altered. (For example in response to USER_SWITCHED in our broadcast receiver) - */ - void rebindListenerServices() { - final int currentUser = ActivityManager.getCurrentUser(); - String flat = Settings.Secure.getStringForUser( - mContext.getContentResolver(), - Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, - currentUser); - - NotificationListenerInfo[] toRemove = new NotificationListenerInfo[mListeners.size()]; - final ArrayList toAdd; - - synchronized (mNotificationList) { - // unbind and remove all existing listeners - toRemove = mListeners.toArray(toRemove); - - toAdd = new ArrayList(); - final HashSet newEnabled = new HashSet(); - final HashSet newPackages = new HashSet(); - - // decode the list of components - if (flat != null) { - String[] components = flat.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR); - for (int i=0; i=0; i--) { - final NotificationListenerInfo info = mListeners.get(i); - if (name.equals(info.component) - && info.userid == userid) { - // cut old connections - if (DBG) Slog.v(TAG, " disconnecting old listener: " + info.listener); - mListeners.remove(i); - if (info.connection != null) { - mContext.unbindService(info.connection); - } - } - } - - Intent intent = new Intent(NotificationListenerService.SERVICE_INTERFACE); - intent.setComponent(name); - - intent.putExtra(Intent.EXTRA_CLIENT_LABEL, - com.android.internal.R.string.notification_listener_binding_label); - intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( - mContext, 0, new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS), 0)); - - try { - if (DBG) Slog.v(TAG, "binding: " + intent); - if (!mContext.bindServiceAsUser(intent, - new ServiceConnection() { - INotificationListener mListener; - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - synchronized (mNotificationList) { - mServicesBinding.remove(servicesBindingTag); - try { - mListener = INotificationListener.Stub.asInterface(service); - NotificationListenerInfo info = new NotificationListenerInfo( - mListener, name, userid, this); - service.linkToDeath(info, 0); - mListeners.add(info); - } catch (RemoteException e) { - // already dead - } - } - } - - @Override - public void onServiceDisconnected(ComponentName name) { - Slog.v(TAG, "notification listener connection lost: " + name); - } - }, - Context.BIND_AUTO_CREATE, - new UserHandle(userid))) - { - mServicesBinding.remove(servicesBindingTag); - Slog.w(TAG, "Unable to bind listener service: " + intent); - return; - } - } catch (SecurityException ex) { - Slog.e(TAG, "Unable to bind listener service: " + intent, ex); - return; - } - } - } - - /** - * Remove a listener binder directly - */ - @Override - public void unregisterListener(INotificationListener listener, int userid) { - // no need to check permissions; if your listener binder is in the list, - // that's proof that you had permission to add it in the first place - - synchronized (mNotificationList) { - final int N = mListeners.size(); - for (int i=N-1; i>=0; i--) { - final NotificationListenerInfo info = mListeners.get(i); - if (info.listener.asBinder() == listener.asBinder() - && info.userid == userid) { - mListeners.remove(i); - if (info.connection != null) { - mContext.unbindService(info.connection); - } - } - } - } - } - - /** - * Remove a listener service for the given user by ComponentName - */ - private void unregisterListenerService(ComponentName name, int userid) { - checkCallerIsSystem(); - - synchronized (mNotificationList) { - final int N = mListeners.size(); - for (int i=N-1; i>=0; i--) { - final NotificationListenerInfo info = mListeners.get(i); - if (name.equals(info.component) - && info.userid == userid) { - mListeners.remove(i); - if (info.connection != null) { - try { - mContext.unbindService(info.connection); - } catch (IllegalArgumentException ex) { - // something happened to the service: we think we have a connection - // but it's bogus. - Slog.e(TAG, "Listener " + name + " could not be unbound: " + ex); - } - } - } - } - } - } - - /** - * asynchronously notify all listeners about a new notification - */ - private void notifyPostedLocked(NotificationRecord n) { - // make a copy in case changes are made to the underlying Notification object - final StatusBarNotification sbn = n.sbn.clone(); - for (final NotificationListenerInfo info : mListeners) { - mHandler.post(new Runnable() { - @Override - public void run() { - info.notifyPostedIfUserMatch(sbn); - }}); - } - } - - /** - * asynchronously notify all listeners about a removed notification - */ - private void notifyRemovedLocked(NotificationRecord n) { - // make a copy in case changes are made to the underlying Notification object - // NOTE: this copy is lightweight: it doesn't include heavyweight parts of the notification - final StatusBarNotification sbn_light = n.sbn.cloneLight(); - - for (final NotificationListenerInfo info : mListeners) { - mHandler.post(new Runnable() { - @Override - public void run() { - info.notifyRemovedIfUserMatch(sbn_light); - }}); - } - } - - // -- APIs to support listeners clicking/clearing notifications -- - - private NotificationListenerInfo checkListenerToken(INotificationListener listener) { - final IBinder token = listener.asBinder(); - final int N = mListeners.size(); - for (int i=0; i list = new ArrayList(); - synchronized (mNotificationList) { - final int N = mNotificationList.size(); - for (int i=0; i Date: Thu, 29 Aug 2013 11:21:23 +0100 Subject: [PATCH 31/31] revert HALO 2 Changes (for now) --- .../res/drawable-hdpi/halo_pinned_app.png | Bin 1658 -> 0 bytes .../res/drawable-hdpi/halo_system_message.png | Bin 1394 -> 0 bytes .../res/drawable-mdpi/halo_pinned_app.png | Bin 1373 -> 0 bytes .../res/drawable-mdpi/halo_system_message.png | Bin 1272 -> 0 bytes .../res/drawable-nodpi/halo_speech_l_d.9.png | Bin 2608 -> 0 bytes .../res/drawable-nodpi/halo_speech_l_u.9.png | Bin 2560 -> 0 bytes .../res/drawable-nodpi/halo_speech_r_d.9.png | Bin 2597 -> 0 bytes .../res/drawable-nodpi/halo_speech_r_u.9.png | Bin 2578 -> 0 bytes .../res/drawable-xhdpi/halo_pinned_app.png | Bin 1873 -> 0 bytes .../drawable-xhdpi/halo_system_message.png | Bin 1512 -> 0 bytes packages/SystemUI/res/layout/halo_bubble.xml | 15 - packages/SystemUI/res/layout/halo_number.xml | 32 +- packages/SystemUI/res/layout/halo_speech.xml | 74 +- packages/SystemUI/res/layout/halo_trigger.xml | 15 - packages/SystemUI/res/values/dimens.xml | 10 +- packages/SystemUI/res/values/strings.xml | 10 +- .../systemui/statusbar/BaseStatusBar.java | 43 +- .../systemui/statusbar/NotificationData.java | 7 +- .../statusbar/halo/CustomObjectAnimator.java | 12 +- .../android/systemui/statusbar/halo/Halo.java | 687 +++++------------- .../statusbar/halo/HaloProperties.java | 243 ++----- 21 files changed, 329 insertions(+), 819 deletions(-) delete mode 100755 packages/SystemUI/res/drawable-hdpi/halo_pinned_app.png delete mode 100755 packages/SystemUI/res/drawable-hdpi/halo_system_message.png delete mode 100755 packages/SystemUI/res/drawable-mdpi/halo_pinned_app.png delete mode 100755 packages/SystemUI/res/drawable-mdpi/halo_system_message.png delete mode 100755 packages/SystemUI/res/drawable-nodpi/halo_speech_l_d.9.png delete mode 100755 packages/SystemUI/res/drawable-nodpi/halo_speech_l_u.9.png delete mode 100755 packages/SystemUI/res/drawable-nodpi/halo_speech_r_d.9.png delete mode 100755 packages/SystemUI/res/drawable-nodpi/halo_speech_r_u.9.png delete mode 100755 packages/SystemUI/res/drawable-xhdpi/halo_pinned_app.png delete mode 100755 packages/SystemUI/res/drawable-xhdpi/halo_system_message.png diff --git a/packages/SystemUI/res/drawable-hdpi/halo_pinned_app.png b/packages/SystemUI/res/drawable-hdpi/halo_pinned_app.png deleted file mode 100755 index ee2dfbb033ce15579b490a23044c11b5a16a259b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1658 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)yHL!FuFg7(ZG;}p~G&DAJGk0+`v9xq@ zws16q>2=9ZF3nBND}m`vf$McNz^NCM6mkoIHoK%2WtOF;xE1B+DuBIgm5JLeE;!AD z>P^Av7E4#0di8;h(Fa8=QbfaqfT;(>geO}d2cGa#^MI+n2$-y2t(a=Uz`*p*)5S5Q z;?|p)C$mKyMUL$*NsHm=kWyYGevsAHLq(;kkkhe)OKXLP-#^ACg;$;*XK=**;V$}Q z;CQgd#b2xIcE-3~LZgU_B$xsD99(f}^bMTZm^0?*h@D9si>yK2JYfu`Me=ZCc=c z)@2P$o^kux`x@rF)cfM8c6)Y-0k2nrd)L|FX$kB*xWz74xGEYobRS4B5ZGf> z$~Lc=@oYxB(y5a9V!MK8uQYzJHE@HFh{l17G2Us zw(E|EOc*5#raXVD;D5m-hrwBmQzE57jLGf({ZntQv--KqGDja|{2+LT@n?hG_8ZGR zv?SmEN;(uhv#&8nWabX;n)I-_Oota-zpj4xeQ^TQA5MpL{!N*3d+R3e`R*t(vqHIo zE3DwkRIw8I1CqB`Yh3iHTbZ>t3>BEBWgZjVIqmdwUxl+P*Qfn) z;+i0FlWE;Y%SU$JJDz-V6J)-9K>44?z302TnjaY{q)SykG_!bf`o{AaH~bp62XY87 z&u{3n>N2=n!THCza1Z~96LHJBRnju|JU4Srl=#2@^olEb)!B1c&;LkixP3$|LAS!O z{%ojcKo?I@snMgUMJ+djVl+jBi;Dl8Db!*ce4`sVklXJh9uD7s$z^ZW6= zu!%|U%(r_kS@HVHK5Ird$4=Kl3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y2=9ZF3nBND}m`vLFl!>sTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6rvIL(9V zO~LIJGn{($fsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tR1?NUNSH+KJ#>O45_&F zX69+H!ww>C!dveN-0e0OFb|5+aB?(XS1TyLK>9oDcD-8u>3Ut#f-d1ldlkAKg++Dc zUQ+wW|F2OoL+@?R#tJsOLnhD9oUymHG@g9JQ6OS*%&|3s`brKg9Snj2IWrBeW<(8GNUWH$O zkiEeD)`7rRf_(2?zs~C0SK1OF@%nj!RLMb+7Y)`Q+-AFO;7w~-d_%73^djdK=Pq=l zeHRSbw{i7{xG(yZUvy1cwn<#pbABQ_MflC>Erl;G`)u@2y-}Jl|KWqi!U9Gq&TqW8 zTDIBMe(#Do5q2oV=hp+R=JTSty1&-`Z=HJMSg% zDE`G}hP;ClH5v62IxFu#3!Qt=^Vtst#c0)^E!V?05mo=hJ1DZU&Wtp00i_>zopr03*}) An*aa+ diff --git a/packages/SystemUI/res/drawable-mdpi/halo_pinned_app.png b/packages/SystemUI/res/drawable-mdpi/halo_pinned_app.png deleted file mode 100755 index 3b25cd27bde4efe7c4b9f88e4a93a50b9d56f9c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1373 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y2=9ZF3nBND}m`vLFjeCsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6rXIL(9V zO~LIJC!BiqfsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tbfcGJ;1=gc+u0vF{I+w zo9TPK4?9R43ts)`x}K6%=c8pE^=%0#JWD@&b$6xM-tmO~bjyQ@&B+Lpn`Vjs+!liYE z@Sf(ngws20^cy?_F7D+pUci4P#_)84NX*M~O~w;gN~H{bu<-aD=edz##y#nQ(3+}$ z=Zh|eItos4?7XQUzT{+lYQo@w*#hU_ZKKEOQ$J$0>@{&hvmjcS8bO*=-s`k(Kc+S=-fwjQ$MhX9GvuS m`=f~8m)GPjxXQMVRf0jXXOo-o&O6&d1)is?pUXO@geCy_d-Cc4 diff --git a/packages/SystemUI/res/drawable-mdpi/halo_system_message.png b/packages/SystemUI/res/drawable-mdpi/halo_system_message.png deleted file mode 100755 index da27042a46b787c9b689aea5f1dc4f427c8b8e46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1272 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y2=9ZF3nBND}m`vLFl!_sTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6q^IL(9V zO~LIJbDVnhfsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tfRL5GGkz1%<*(_45_&F zX4*lo!v+$^Czoz+>Z+3TxS1%(s!| z1WzV8N3LfoPa~3MpD+95?H3m1=jAOKY`uKT9rk+%1%I%fPdM{YyMV8%$8%N%>-Gdk zH_?9+pY6|lB--qqZ-EL58Oq0)Tc^$ zvo5{3uwL5dz|7ae9b0$!c;9>c^-|If`zcDh-T2fQ>xC_Vw;CPgkB?E)S!U+Tv)*4SBU@hP{3>JsRKsUh>YfZ!xh&UVgj|%~L z<1vGYzGSx_zMz!@B19nI64B_0hzL}K6$<3-L1XRg?B+ReI7`UFk{`(t(1n&9{@Miw zGQel>SX==M^J3A)SlHqA+MSdp@sk)_j34 z@SiY#Y0alaasjk2zz6s77|?kHuU!B`+Wozwc|#}~qBoBP9SS{+3^Mky0gix5c0fR1 zP)rt+h_`mJv$i3-66`PpS1T;m7K^hZIg_jjR<>kY8ynIB$FHz%)_5|>jf}(C;BBy2 zS1S@Eo+}BDC*f=f&KNuV0+!0*3+NmMu;7;k`Tc>#{w}Hl zKLq5$UA7Y7rhY6A6O7=S%^%PAY{>wRwI5)*@jy2Go4!QWFZ|;P|10nBSmytu85#-( zJzpIERV)izPzBCUf0jP9_}M%F2kICe)Ee&$!5A29aUhlKOcOqt*tIE4*IjR*C!ng6 zI#F9NayZCD>o<{3Iz^87t+g>v^1|k<2EPnC zPPMFcN&}=j)nHCDpTAywHaLW6Yj1a{QCUQf#h7{PckH-Iee9zU7yndpZHZBv-iGDc zf$#~fBrU>dzt2^N$MR*$>IJZZymE%|LH$re!|1v6z}uSQpiV_*n{w9NOUYEZbhe_> z0%k@*rly)Q&OKZg|0KThPL|e4xY$W&?_p(4O6-Jk&u{1({SDCwvcXCpQ)BJQslwVb zNv-QXeNjo!d$*Y5-F;C-k9_yznDdOdu-AoDb zrWjU|DK5F2OpjFKodCHiEJ6TyPRVlHwN3h(&{UIZJ(+{=BfSHYtZ7pRZYmeC~o$ri= zUCHV<%@w$ONGt#9PAWTD<;*k7Vaa>Vh;?cmFI6voF=(t$Ikl9!-)p8ShVZ(tpnbK$ zCR?`~M^veIu}@e!x_jSrI^BU6)dy_YtvQ`3^vimX_NmvVrnxyo`QFec(X-n`VX@Oh z`grsxtu{iQ%nHYKSic)NJWz(bl5DCraQiv{X1||qPnWgrSh0F%wz?*I8)C)fP08NQ zZ`>-B+{cKThVkcAPE_SLpOLn&T(f6R93-_Bs!FGZ2HtN>!0($VJgV5Fak&dY%vF)- z=(<*y^$k1P_r^SvP*y(3Pno>tb*yyyKx3w<+V7&Q4K-`x2NR<{&9pZf4`|;ZXk1X- zQc`%yBr$GIwBq?rU8U&L7)Se(u_u zlB9f}7EyIwr^9aj9=rU=4`r&-sHRU%?RgzTS3h{FCG4Qy>};=HXT~(JI?xO54hSDC zo6V{1{@5@zDYT8RFYlo+jnecDXJAWX|<1bGi9@O`J>mUw`>)xmTdv z)NIR~{6g8{pAX~_rQnERZ|nPh01Hz z)}0w`rLjNEGNmlPh;mtr<*8+t7}8<`(UT-fHn}xA_C$&gV?;pE4)>hJnxD&?F&?bm ztY@-3RKCBw2Ki`JiqEku;UemKQMvCb)x~G!j}^yXj3<56w9WCf2u*02>X3_M<#Eqa z-N>Geb@dNLmz@5rzLmjV6*9`^=qhzRI&87+iph3e?PZZhH*U_HZQJ06dgxyKYTS$6 z&$fy`q$(amW>6kWhD9ArwYY(rjhRIc24b|p*WC|_CPBABtg9g)(9d`@n(Xf=H$2g& zV?j{qEvi4wdbh(e<*jo1TfkwI_A>tt@iZK~xHU$y`)h?UcY11OsOdD4pJe}sJZ#rJ zS-;e8K;qbw$}n}5k1R$RghMKw-}~luf=olG9IC`tJ$VHa8MoeV^W3VxoOIHjdK$*s z6&#$Ni7>9HAhg#o&)vUDPRG8jjkh?+SmAnvyevp(IBorh@veX_$I8Iwo1&6K*LE>p zeV&Ly#(H~@Q%7_DfK zYEyJ%)!DKEjo_8kC6O>4%2-%_o<&LDiZ2HoQ9AN&&y(tt{*#Hv_8Q+ODs@#E1g4&n k6mJmM_%D5X1EvH^+;Pt;{lq`U=l|iTuA9mEq`)O@ zNMvG|A_^4AbBhy0esNy@?6@el9S7m$2-wR>DgizuWdU-2v_L|VJ0L#ml2r5gZ8QS- z43S1TAig*i#Pk6uLNNpoQFv=M28#ti5QQZWK@e*N;4oMm8l$>FYb=381W7m>;Om7@ zSrc=(BwwoQS6ix;10qr?6_L{p#YdyWQ7Z3qz(v`r(Z(gi^XKFGjFw1! zq5rt?U9`kMRs^AaA&D?X%vPNT*K~ob%H7`^ng^=9A$f~=szYH#Q-$mpJ|vJbs169# z7ZiubArT1_JAw_B2HIgj8Xk+a#p3K-oLvYY-j-@>W8<=*@jWh$>Ov$?L060o(FTj9 z;q3@GER}*I(rhW93ynrt;4%afDNDeH7VPp=cE56If6FCN#1Km=6#EN>(F+ye6DgDm zC6PiAK=A_sWFSw#5y~V#%^%N~XsM8xw-e&HiiLdObACy@@7O1T|10hIE7%$P}SZ zH@cjAn06@@6 zu})R1!m;t=TMsRrY4{AB(tpx&@pRSE^edNkwqC7E4`{L|wA6&n#h0wrJMywKyIuV} zjuXQwdqJ;z>y~|H_*}yNW7KSoqdq9aTQiMl1NcER;;hFFT~>JOp8DdV!gxkxf!+&d=nCF;n-pZMomZTYy@mP1_l_BBU;0U{*#q-6B?B+g<9Yoe6uuDAYDQ ztl>jHsYb9UOg9OrvDmZCIHQc44^tn}s$V?OkG%L>N>Ohzycj9N;mMWvva+~ltr~9L zTTMEDbZ^lP4(aaecUe1wN_`p6IF{*x*;Bo8E&bHOVcbTY{ zx%Y9pR7c~?3?jnhXhH9m$+my9g101hN#3Q`ly^0g^IUt!pPxL06>28^$QnJb=o=oT zEvwv^-<6XvzMuZGPI@q0R&Y7L@7N{Ssiu&3&kTjJ35v$dihp-(K2OZa&eC9|G^lVO%(ENb)Qa((M9Llyr}sPWbXb()M|wWY~fwjaHF^mcT# zV*+fp_sTb6s>LVk>JyNqrM)(j%0ob`8B!{t$HuNm52SO|o+vb1yz>XmD%6 zqd9f%-UF|4wU(?x54mcZN5!*OU1{@t)z+VRC?a(Khrqy*$L4p=2jeRVQxT!epJVl2 z7xd+=iaD`NIZ^sZjp09;IM=uKTG{$4Xyfj_DCL-81Tj&T#^}X;_>&M_ zJ2+hAvl7Wdo~X9t9@hsC$V~u{}QXST?v>ExTeT zfRN8EE!9~BFMuZoZ|a=&c_Mx*QRo{_JS6CAv>lBotG`=~0pt~*GWbF3KG0`%V9PFHWf5860z&*6?i-F`lGURyKh_h&Y zzP01j480mXyVHy#gO45wPKDN|dKm1TGv9%}AJJ={c=^qrv);C`55~^MS0kSXZD%Cs zlz8@qmY|(#A|mdTFSTw?hwPM4WygU7+F-HbzW$*WVuJIh3l8ani#`=%DI?{*p}JL_ z#NvYdlCY1d7IPynCTFK75~{~;yxU7d_pd5{pt*fa* zi&+B3wZG~R zWei^kG-hfoUqb0QgETU{=j%1@nSsJ(tpXLESH%SZO=`BaZ^^>*&83Q!tC!uPGBXr? z^dla>)W+}B>n=Eb^P$gD3xD>fj|#oSy4`5$x_J7URQTPvshso;zIoH;sr%jQ?+nYW z5Rll{L{oPUcb`4UGAFVEU*JYH>|cG&ed~!}XiKtLfhAuzGggZevo+%}^7`Erj+bfF z@lDr%dOtAZb29^(lsOh$#WTeJacwlD#3V61FJ-FED(Fv=fon#v$3@2TN3VvOOgprN zn(xUdAA@z|vU++Y@%P1C0}nVIrn5TjfgM<_Z@P_Kr)RAze`>WxOL_LBLEz~X>nF9h m&c%@fybc3Tk{+}*sB6QJRcTGQyvdUJe=-Kmi(26lmh=}G(JUMQ diff --git a/packages/SystemUI/res/drawable-nodpi/halo_speech_r_d.9.png b/packages/SystemUI/res/drawable-nodpi/halo_speech_r_d.9.png deleted file mode 100755 index f412194527f6b9c3c0339526a5a2ab83894250c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2597 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 DUJotn diff --git a/packages/SystemUI/res/drawable-xhdpi/halo_pinned_app.png b/packages/SystemUI/res/drawable-xhdpi/halo_pinned_app.png deleted file mode 100755 index a2e31517e003dd04610b0c39d484039fbb059207..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1873 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 diff --git a/packages/SystemUI/res/layout/halo_bubble.xml b/packages/SystemUI/res/layout/halo_bubble.xml index f1e2be091fc..39d96921b97 100644 --- a/packages/SystemUI/res/layout/halo_bubble.xml +++ b/packages/SystemUI/res/layout/halo_bubble.xml @@ -1,19 +1,4 @@ - - - - + android:layout_width="wrap_content" + android:layout_height="wrap_content"> diff --git a/packages/SystemUI/res/layout/halo_speech.xml b/packages/SystemUI/res/layout/halo_speech.xml index 4b933fedbd5..052c3bbe544 100644 --- a/packages/SystemUI/res/layout/halo_speech.xml +++ b/packages/SystemUI/res/layout/halo_speech.xml @@ -1,51 +1,51 @@ - - + android:layout_height="wrap_content"> + android:id="@+id/container" + android:layout_width="@dimen/halo_content_max_width" + android:layout_height="wrap_content"> - - + android:layout_height="wrap_content"> + + + + + + diff --git a/packages/SystemUI/res/layout/halo_trigger.xml b/packages/SystemUI/res/layout/halo_trigger.xml index b11906515bc..f16a4a7a41d 100644 --- a/packages/SystemUI/res/layout/halo_trigger.xml +++ b/packages/SystemUI/res/layout/halo_trigger.xml @@ -1,19 +1,4 @@ - - 24dp 16dp 14sp - 16sp - 4dp - 13dp - 3dp - 3dp + 15sp + 10dp + 18dp + 7dp + 7dp 250dp diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index dceecdcfef1..d8857d67807 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -670,10 +670,10 @@ Dismiss notification Hide - Dismiss all notifications - Hide & silence until woken - This is HALO - Move me: 2x-tap & drag - Browse tasks: Horizontal drag + Clear all notifications + Hide and silence until woken + I am HALO. + Double-tap-drag to move me around, drag to task. + Change my behavior in the settings. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 29ed3849339..88f964196f0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -76,7 +76,6 @@ import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.widget.FrameLayout; -import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.PopupMenu; @@ -1516,32 +1515,7 @@ public void run() { return entry.notification; } - public void prepareHaloNotification(NotificationData.Entry entry, StatusBarNotification notification, boolean update) { - - Notification notif = notification.getNotification(); - - // Get the remote view - try { - - if (!update) { - ViewGroup mainView = (ViewGroup)notif.contentView.apply(mContext, null, mOnClickHandler); - - if (mainView instanceof FrameLayout) { - entry.haloContent = mainView.getChildAt(1); - mainView.removeViewAt(1); - } else { - entry.haloContent = mainView; - } - } else { - notif.contentView.reapply(mContext, entry.haloContent, mOnClickHandler); - } - - } catch (Exception e) { - // Non uniform content? - android.util.Log.d("PARANOID", " Non uniform content?"); - } - - + private Bitmap createRoundIcon(StatusBarNotification notification) { // Construct the round icon final float haloSize = Settings.System.getFloat(mContext.getContentResolver(), Settings.System.HALO_SIZE, 1.0f); @@ -1580,8 +1554,8 @@ public void prepareHaloNotification(NotificationData.Entry entry, StatusBarNotif } catch (Exception e) { // NameNotFoundException } - } - entry.roundIcon = roundIcon; + } + return roundIcon; } protected StatusBarIconView addNotificationViews(IBinder key, @@ -1606,9 +1580,9 @@ protected StatusBarIconView addNotificationViews(IBinder key, return null; } - NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView); - prepareHaloNotification(entry, notification, false); - entry.hide = entry.notification.getPackageName().equals("com.paranoid.halo"); + NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView, + createRoundIcon(notification)); + entry.hide = entry.notification.pkg.equals("com.paranoid.halo"); final PendingIntent contentIntent = notification.notification.contentIntent; if (contentIntent != null) { @@ -1769,7 +1743,7 @@ public void updateNotification(IBinder key, StatusBarNotification notification) oldEntry.floatingIntent = null; } // Update the roundIcon - prepareHaloNotification(oldEntry, notification, true); + oldEntry.roundIcon = createRoundIcon(notification); // Update the icon. final StatusBarIcon ic = new StatusBarIcon(notification.pkg, @@ -1832,9 +1806,6 @@ public void updateNotification(IBinder key, StatusBarNotification notification) mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER); } } - - // Update halo - if (mHalo != null) mHalo.update(); } // Q: What kinds of notifications should show during setup? diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java index a20a6086463..2f40b7e5d00 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java @@ -40,7 +40,6 @@ public static final class Entry { public View row; // the outer expanded view public View content; // takes the click events and sends the PendingIntent public View expanded; // the inflated RemoteViews - public View haloContent; public ImageView largeIcon; protected boolean hide = false; protected Bitmap roundIcon; @@ -52,6 +51,12 @@ public Entry(IBinder key, StatusBarNotification n, StatusBarIconView ic) { this.notification = n; this.icon = ic; } + public Entry(IBinder key, StatusBarNotification n, StatusBarIconView ic, Bitmap ri) { + this.key = key; + this.notification = n; + this.icon = ic; + this.roundIcon = ri; + } public void setLargeView(View expandedLarge) { this.expandedLarge = expandedLarge; writeBooleanTag(row, R.id.expandable_tag, expandedLarge != null); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java index 0152af50361..1bacaf14898 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/CustomObjectAnimator.java @@ -29,14 +29,13 @@ public class CustomObjectAnimator { private View rootView; private Handler handler = new Handler(); private ObjectAnimator animator; - private boolean delayed = false; public CustomObjectAnimator(View root) { rootView = root; } public boolean isRunning() { - return animator != null && (animator.isRunning() || delayed); + return animator != null && animator.isRunning(); } public void animate(ObjectAnimator newInstance, TimeInterpolator interpolator, AnimatorUpdateListener update) { @@ -46,11 +45,9 @@ public void animate(ObjectAnimator newInstance, TimeInterpolator interpolator, A public void animate(final ObjectAnimator newInstance, final TimeInterpolator interpolator, final AnimatorUpdateListener update, long startDelay, final Runnable executeAfter) { - delayed = true; handler.postDelayed(new Runnable() { public void run() { runAnimation(newInstance, interpolator, update, executeAfter); - delayed = false; }}, startDelay); } @@ -64,13 +61,9 @@ private void runAnimation(ObjectAnimator newInstance, TimeInterpolator interpola // Invalidate if (update == null) { animator.addUpdateListener(new AnimatorUpdateListener() { - float oldValue = -1f; - @Override public void onAnimationUpdate(ValueAnimator animation) { - final float value = animation.getAnimatedFraction(); - if (value != oldValue) rootView.postInvalidate(); - oldValue = value; + rootView.invalidate(); }}); } else { animator.addUpdateListener(update); @@ -97,6 +90,5 @@ public void onAnimationUpdate(ValueAnimator animation) { public void cancel(boolean unschedule) { if (unschedule) handler.removeCallbacksAndMessages(null); if (animator != null) animator.cancel(); - delayed = false; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java index 16f3d50274f..c2a6197aa26 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/Halo.java @@ -30,10 +30,7 @@ import android.animation.ValueAnimator.AnimatorUpdateListener; import android.animation.Keyframe; import android.animation.PropertyValuesHolder; -import android.content.BroadcastReceiver; -import android.content.IntentFilter; import android.content.pm.ApplicationInfo; -import android.content.ComponentName; import android.content.Context; import android.content.ContentResolver; import android.content.SharedPreferences; @@ -52,7 +49,6 @@ import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Point; -import android.graphics.PointF; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuff.Mode; @@ -64,7 +60,6 @@ import android.os.Vibrator; import android.os.ServiceManager; import android.provider.Settings; -import android.service.notification.INotificationListener; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.ExtendedPropertiesUtils; @@ -100,7 +95,6 @@ import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.ScrollView; -import android.widget.ImageButton; import com.android.systemui.R; import com.android.systemui.statusbar.BaseStatusBar.NotificationClicker; @@ -147,7 +141,6 @@ enum Gesture { private SettingsObserver mSettingsObserver; private GestureDetector mGestureDetector; private KeyguardManager mKeyguardManager; - private BroadcastReceiver mReceiver; private HaloEffect mEffect; private WindowManager.LayoutParams mTriggerPos; @@ -156,8 +149,6 @@ enum Gesture { private View mRoot; private View mContent, mHaloContent; - private INotificationListener mHaloListener; - private ComponentName mHaloComponent; private NotificationData.Entry mLastNotificationEntry = null; private NotificationData.Entry mCurrentNotficationEntry = null; private NotificationClicker mContentIntent, mTaskIntent; @@ -185,7 +176,6 @@ enum Gesture { private int mScreenWidth, mScreenHeight; private int mKillX, mKillY; private int mMarkerIndex = -1; - private int mDismissDelay = 100; private int oldIconIndex = -1; private float initialX = 0; @@ -242,33 +232,6 @@ public void onChange(boolean selfChange) { } } - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - - if (!mAttached) { - mAttached = true; - mSettingsObserver = new SettingsObserver(new Handler()); - mSettingsObserver.observe(); - } - mHandler.postDelayed(new Runnable() { - public void run() { - final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); - mEffect.animateHaloBatch(0, c, false, 500, HaloProperties.MessageType.MESSAGE); - } - }, 2500); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - - if (mAttached) { - mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); - mAttached = false; - } - } - public Halo(Context context, AttributeSet attrs) { this(context, attrs, 0); } @@ -288,13 +251,6 @@ public Halo(Context context, AttributeSet attrs, int defStyle) { mRoot = this; mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); - IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); - - filter.addAction(Intent.ACTION_USER_PRESENT); - - mReceiver = new ScreenReceiver(); - mContext.registerReceiver(mReceiver, filter); - // Init variables mInteractionReversed = Settings.System.getInt(mContext.getContentResolver(), Settings.System.HALO_REVERSED, 1) == 1; @@ -332,7 +288,7 @@ public Halo(Context context, AttributeSet attrs, int defStyle) { WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, PixelFormat.TRANSLUCENT); @@ -369,12 +325,6 @@ private void initControl() { // Get actual screen size mScreenWidth = mEffect.getWidth(); mScreenHeight = mEffect.getHeight(); - - mKillX = mScreenWidth / 2; - mKillY = mIconHalfSize; - - // In the unlikely event the user still holds on to HALO just let it be - if (mState != State.IDLE) return; // Halo dock position preferences = mContext.getSharedPreferences("Halo", 0); @@ -386,6 +336,9 @@ private void initControl() { preferences.edit().putBoolean(KEY_HALO_FIRST_RUN, false).apply(); } + mKillX = mScreenWidth / 2; + mKillY = mIconHalfSize; + if (!mFirstStart) { if (msavePositionY < 0) mEffect.setHaloY(0); float mTmpHaloY = (float) msavePositionY / mScreenWidth * (mScreenHeight); @@ -409,7 +362,8 @@ private void initControl() { // Halo dock position mTickerLeft = msavePositionX == 0 ? true : false; updateTriggerPosition(msavePositionX, msavePositionY); - mEffect.updateResources(mTickerLeft); + mEffect.mHaloTextViewL.setVisibility(mTickerLeft ? View.VISIBLE : View.GONE); + mEffect.mHaloTextViewR.setVisibility(mTickerLeft ? View.GONE : View.VISIBLE); mEffect.setHaloY(msavePositionY); if (mState == State.FIRST_RUN) { @@ -418,13 +372,13 @@ private void initControl() { mHandler.postDelayed(new Runnable() { public void run() { mEffect.wake(); - mEffect.ticker(mContext.getResources().getString(R.string.halo_tutorial1), 0, 3000); + tick(mLastNotificationEntry, mContext.getResources().getString(R.string.halo_tutorial1), 0, 3000, true); mHandler.postDelayed(new Runnable() { public void run() { - mEffect.ticker(mContext.getResources().getString(R.string.halo_tutorial2), 0, 3000); + tick(mLastNotificationEntry, mContext.getResources().getString(R.string.halo_tutorial2), 0, 3000, true); mHandler.postDelayed(new Runnable() { public void run() { - mEffect.ticker(mContext.getResources().getString(R.string.halo_tutorial3), 0, 3000); + tick(mLastNotificationEntry, mContext.getResources().getString(R.string.halo_tutorial3), 0, 3000, true); mHandler.postDelayed(new Runnable() { public void run() { mState = State.IDLE; @@ -448,10 +402,6 @@ private boolean isLandscapeMod() { return mScreenWidth < mScreenHeight; } - public void update() { - if (mEffect != null) mEffect.invalidate(); - } - private void updateTriggerPosition(int x, int y) { try { mTriggerPos.x = x; @@ -463,19 +413,20 @@ private void updateTriggerPosition(int x, int y) { } private void loadLastNotification(boolean includeCurrentDismissable) { - if (getHaloMsgCount() > 0) { - mLastNotificationEntry = mNotificationData.get(getHaloMsgIndex(getHaloMsgCount() - 1, false)); + if (mNotificationData.size() > 0) { + mLastNotificationEntry = mNotificationData.get(mNotificationData.size() - 1); // If the current notification is dismissable we might want to skip it if so desired if (!includeCurrentDismissable) { - if (getHaloMsgCount() > 1 && mLastNotificationEntry != null && - mCurrentNotficationEntry != null && + if (mNotificationData.size() > 1 && mLastNotificationEntry != null && mLastNotificationEntry.notification == mCurrentNotficationEntry.notification) { - if (mLastNotificationEntry.notification.isClearable()) { - mLastNotificationEntry = mNotificationData.get(getHaloMsgIndex(getHaloMsgCount() - 2, false)); - } - } else if (getHaloMsgCount() == 1) { - if (mLastNotificationEntry.notification.isClearable()) { + boolean cancel = (mLastNotificationEntry.notification.notification.flags & + Notification.FLAG_AUTO_CANCEL) == Notification.FLAG_AUTO_CANCEL; + if (cancel) mLastNotificationEntry = mNotificationData.get(mNotificationData.size() - 2); + } else if (mNotificationData.size() == 1) { + boolean cancel = (mLastNotificationEntry.notification.notification.flags & + Notification.FLAG_AUTO_CANCEL) == Notification.FLAG_AUTO_CANCEL; + if (cancel) { // We have one notification left and it is dismissable, clear it... clearTicker(); return; @@ -488,8 +439,8 @@ private void loadLastNotification(boolean includeCurrentDismissable) { && mLastNotificationEntry.notification.notification.tickerText != null) { mNotificationText = mLastNotificationEntry.notification.notification.tickerText.toString(); } - - tick(mLastNotificationEntry, 0, 0, false, false, false); + + tick(mLastNotificationEntry, "", 0, 0, false); } else { clearTicker(); } @@ -497,13 +448,6 @@ private void loadLastNotification(boolean includeCurrentDismissable) { public void setStatusBar(BaseStatusBar bar) { mBar = bar; - mHaloComponent = new ComponentName("HaloComponent", "Halo.java"); - mHaloListener = new HaloReceiver(); - try { - mNotificationManager.registerListener(mHaloListener, mHaloComponent, 0); - } catch (android.os.RemoteException ex) { - // failed to register listener - } if(ExtendedPropertiesUtils.isTablet()) { if (mBar.getTabletTicker() != null) mBar.getTabletTicker().setUpdateEvent(this); } else { @@ -514,6 +458,7 @@ public void setStatusBar(BaseStatusBar bar) { } void launchTask(NotificationClicker intent) { + // Do not launch tasks in hidden state or protected lock screen if (mState == State.HIDDEN || mState == State.SILENT || (mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure())) return; @@ -524,7 +469,6 @@ void launchTask(NotificationClicker intent) { } catch (RemoteException e) { // ... } - mDismissDelay = 1500; if (intent!= null) { intent.onClick(mRoot); @@ -572,7 +516,11 @@ void resetIcons() { final float originalAlpha = mContext.getResources().getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); for (int i = 0; i < mNotificationData.size(); i++) { NotificationData.Entry entry = mNotificationData.get(i); - entry.icon.setAlpha(originalAlpha); + if (entry.notification.pkg.equals("com.paranoid.halo")) { + entry.icon.setAlpha(0); + } else { + entry.icon.setAlpha(originalAlpha); + } } } @@ -580,11 +528,8 @@ void setIcon(int index) { float originalAlpha = mContext.getResources().getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); for (int i = 0; i < mNotificationData.size(); i++) { NotificationData.Entry entry = mNotificationData.get(i); - float alpha = index == i ? 1f : originalAlpha; - - // Persistent notification appear muted - if (!entry.notification.isClearable() && index != i) alpha /= 2; - entry.icon.setAlpha(alpha); + if (entry.notification.pkg.equals("com.paranoid.halo")) continue; + entry.icon.setAlpha(index == i ? 1f : originalAlpha); } } @@ -601,7 +546,6 @@ public boolean onTouchEvent(MotionEvent event) { // Prevent any kind of interaction while HALO explains itself if (mState == State.FIRST_RUN) return true; - mEffect.onTouchEvent(event); mGestureDetector.onTouchEvent(event); final int action = event.getAction(); @@ -648,11 +592,6 @@ public boolean onTouchEvent(MotionEvent event) { if (mOverX) { Settings.System.putInt(mContext.getContentResolver(), Settings.System.HALO_ACTIVE, 0); - try { - mNotificationManager.unregisterListener(mHaloListener,0); - } catch (android.os.RemoteException ex) { - // Failed to un-register listener - } return true; } @@ -668,7 +607,7 @@ public boolean onTouchEvent(MotionEvent event) { playSoundEffect(SoundEffectConstants.CLICK); launchTask(mTaskIntent); } - mEffect.nap(100); + mEffect.nap(0); if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 1500, HaloEffect.SLEEP_TIME, false); } else if (mGesture == Gesture.DOWN2) { @@ -684,32 +623,57 @@ public boolean onTouchEvent(MotionEvent event) { } else if (mGesture == Gesture.UP2) { // Clear all notifications playSoundEffect(SoundEffectConstants.CLICK); - if (getHaloMsgCount()-getHidden() < 1) { - mEffect.nap(1500); - if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); - } + try { - mDismissDelay = 0; - mBar.getService().onClearAllNotifications(); + mBar.getStatusBarService().onClearAllNotifications(); } catch (RemoteException ex) { // system process is dead if we're here. } + + loadLastNotification(false); + + mEffect.nap(1500); + if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); } else if (mGesture == Gesture.UP1) { // Dismiss notification playSoundEffect(SoundEffectConstants.CLICK); - if (getHaloMsgCount()-getHidden() < 1) { - mEffect.nap(1500); - if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); - } + if (mContentIntent != null) { try { - mDismissDelay = 0; mBar.getService().onNotificationClear(mContentIntent.mPkg, mContentIntent.mTag, mContentIntent.mId); } catch (RemoteException ex) { // system process is dead if we're here. } } + + // Find next entry + NotificationData.Entry entry = null; + if (mNotificationData.size() > 0) { + for (int i = mNotificationData.size() - 1; i >= 0; i--) { + NotificationData.Entry item = mNotificationData.get(i); + if (mCurrentNotficationEntry != null + && mCurrentNotficationEntry.notification == item.notification) { + continue; + } + boolean cancel = (item.notification.notification.flags & + Notification.FLAG_AUTO_CANCEL) == Notification.FLAG_AUTO_CANCEL; + if (cancel) { + entry = item; + break; + } + } + } + + // When no entry was found, take the last one + if (entry == null && mNotificationData.size() > 0) { + loadLastNotification(false); + } else { + tick(entry, "", 0, 0, false); + } + + mEffect.nap(1500); + if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); } else { // No gesture, just snap HALO mEffect.snap(0); @@ -779,37 +743,35 @@ public boolean onTouchEvent(MotionEvent event) { boolean oldTickerPos = mTickerLeft; mTickerLeft = (posX + mIconHalfSize < mScreenWidth / 2); if (oldTickerPos != mTickerLeft) { - mEffect.updateResources(mTickerLeft); + mEffect.updateResources(); + mEffect.mHaloTextViewL.setVisibility(mTickerLeft ? View.VISIBLE : View.GONE); + mEffect.mHaloTextViewR.setVisibility(mTickerLeft ? View.GONE : View.VISIBLE); } } } else { // We have three basic gestures, one horizontal for switching through tasks and // two vertical for dismissing tasks or making HALO fall asleep + int deltaX = (int)(mTickerLeft ? event.getRawX() : mScreenWidth - event.getRawX()); int deltaY = (int)(mEffect.getHaloY() - event.getRawY() + mIconSize); int horizontalThreshold = (int)(mIconSize * 1.5f); int verticalThreshold = (int)(mIconSize * 0.25f); int verticalSteps = (int)(mIconSize * 0.7f); String gestureText = mNotificationText; - Gesture oldGesture = Gesture.NONE; // Switch icons if (deltaX > horizontalThreshold) { if (mGesture != Gesture.TASK) mEffect.setHaloOverlay(HaloProperties.Overlay.NONE, 0f); - oldGesture = mGesture; mGesture = Gesture.TASK; deltaX -= horizontalThreshold; - if (mNotificationData != null && getHaloMsgCount() > 0) { - int items = getHaloMsgCount(); + if (mNotificationData != null && mNotificationData.size() > 0) { + int items = mNotificationData.size(); - // This will be the length we are going to use + // This will be the lenght we are going to use int indexLength = ((int)(mScreenWidth * 0.85f) - mIconSize) / items; - // Set a standard (max) distance for markers. - indexLength = indexLength > 120 ? 120 : indexLength; - // Calculate index mMarkerIndex = mTickerLeft ? (items - deltaX / indexLength) - 1 : (deltaX / indexLength); @@ -819,7 +781,7 @@ public boolean onTouchEvent(MotionEvent event) { } // Up & down gestures - } else if (Math.abs(deltaY) > verticalThreshold * 2) { + } else if (Math.abs(deltaY) > verticalThreshold) { mMarkerIndex = -1; boolean gestureChanged = false; @@ -830,32 +792,28 @@ public boolean onTouchEvent(MotionEvent event) { gestureChanged = true; mEffect.setHaloOverlay(HaloProperties.Overlay.NONE, 0f); if (verticalGesture()) gestureText = ""; - oldGesture = mGesture; mGesture = Gesture.NONE; } else if (deltaY > 0) { if (deltaIndex == 1 && mGesture != Gesture.UP1) { - oldGesture = mGesture; mGesture = Gesture.UP1; gestureChanged = true; mEffect.setHaloOverlay(HaloProperties.Overlay.DISMISS, 1f); gestureText = mContext.getResources().getString(R.string.halo_dismiss); } else if (deltaIndex > 1 && mGesture != Gesture.UP2) { - oldGesture = mGesture; mGesture = Gesture.UP2; gestureChanged = true; mEffect.setHaloOverlay(HaloProperties.Overlay.CLEAR_ALL, 1f); gestureText = mContext.getResources().getString(R.string.halo_clear_all); } + } else { if (deltaIndex == 1 && mGesture != Gesture.DOWN1) { - oldGesture = mGesture; mGesture = Gesture.DOWN1; gestureChanged = true; mEffect.setHaloOverlay(mTickerLeft ? HaloProperties.Overlay.BACK_LEFT : HaloProperties.Overlay.BACK_RIGHT, 1f); gestureText = mContext.getResources().getString(R.string.halo_hide); } else if (deltaIndex > 1 && mGesture != Gesture.DOWN2) { - oldGesture = mGesture; mGesture = Gesture.DOWN2; gestureChanged = true; mEffect.setHaloOverlay(mTickerLeft ? HaloProperties.Overlay.SILENCE_LEFT @@ -866,19 +824,22 @@ public boolean onTouchEvent(MotionEvent event) { if (gestureChanged) { mMarkerIndex = -1; - mEffect.ticker(gestureText, 0, 250); + + // Tasking hasn't changed, we can tick the message here + if (mMarkerIndex == oldIconIndex) { + mEffect.ticker(gestureText, 0, 250); + mEffect.updateResources(); + mEffect.invalidate(); + } if (mHapticFeedback) mVibrator.vibrate(10); - gestureChanged = false; } } else { mMarkerIndex = -1; - if (mGesture != Gesture.NONE) { mEffect.setHaloOverlay(HaloProperties.Overlay.NONE, 0f); if (verticalGesture()) mEffect.killTicker(); } - oldGesture = mGesture; mGesture = Gesture.NONE; } @@ -887,19 +848,36 @@ public boolean onTouchEvent(MotionEvent event) { oldIconIndex = mMarkerIndex; // Make a tiny pop if not so many icons are present - if (mHapticFeedback && getHaloMsgCount() < 10) mVibrator.vibrate(10); + if (mHapticFeedback && mNotificationData.size() < 10) mVibrator.vibrate(1); - int iconIndex = getHaloMsgIndex(mMarkerIndex, false); try { - // Tick the first item only if we were tasking before - if (iconIndex == -1 && !verticalGesture() && oldGesture == Gesture.TASK) { + if (mMarkerIndex == -1) { mTaskIntent = null; resetIcons(); - tick(mLastNotificationEntry, 0, -1, false, true, false); + tick(mLastNotificationEntry, gestureText, 0, 250, false); + + // Ping to notify the user we're back where we started + if (mEnableColor) { + mEffect.ping(mPaintHoloCustom, 0); + } else { + mEffect.ping(mPaintHolo, 0); + } } else { - setIcon(iconIndex); - NotificationData.Entry entry = mNotificationData.get(iconIndex); - tick(entry, 0, -1, false, true, false); + setIcon(mMarkerIndex); + NotificationData.Entry entry = mNotificationData.get(mMarkerIndex); + + ApplicationInfo ai; + try { + ai = mPm.getApplicationInfo( entry.notification.pkg, 0); + } catch (final NameNotFoundException e) { + ai = null; + } + String text = (String) (ai != null ? mPm.getApplicationLabel(ai) : "..."); + + if (entry.notification.notification.tickerText != null) { + text = entry.notification.notification.tickerText.toString(); + } + tick(entry, text, 0, 250, false); mTaskIntent = entry.getFloatingIntent(); } } catch (Exception e) { @@ -929,7 +907,6 @@ public void cleanUp() { if (mEffect != null) mWindowManager.removeView(mEffect); // Remove resolver mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); - mContext.unregisterReceiver(mReceiver); } class HaloEffect extends HaloProperties { @@ -987,82 +964,13 @@ public HaloEffect(Context context) { (int)(mMarkerB.getHeight() * mHaloSize), true); } + mMarkerPaint.setAntiAlias(true); mMarkerPaint.setAlpha(0); xPaint.setAntiAlias(true); xPaint.setAlpha(0); - updateResources(mTickerLeft); - } - - void getRawPoint(MotionEvent ev, int index, PointF point){ - final int location[] = { 0, 0 }; - mRoot.getLocationOnScreen(location); - - final int location_effect[] = { 0, 0 }; - getLocationOnScreen(location_effect); - - float x=ev.getX(index); - float y=ev.getY(index); - - double angle=Math.toDegrees(Math.atan2(y, x)); - angle+=mRoot.getRotation(); - - final float length=PointF.length(x,y); - - x=(float)(length*Math.cos(Math.toRadians(angle)))+location[0]; - y=(float)(length*Math.sin(Math.toRadians(angle)))+location[1]; - - point.set((int)x,(int)y - location_effect[1]); - } - - boolean browseView(PointF loc, Rect parent, View v) { - int posX = (int)loc.x; - int posY = (int)loc.y; // - mIconHalfSize / 2; - - if (v instanceof ViewGroup) { - ViewGroup vg = (ViewGroup)v; - for (int i = 0; i < vg.getChildCount(); i++) { - View sv = vg.getChildAt(i); - if (browseView(loc, parent, sv)) return true; - } - } else { - if (v.isClickable()) { - Rect r = new Rect(); - v.getHitRect(r); - - int left = tickerX + parent.left + r.left; - int top = tickerY + parent.top + r.top; - int right = tickerX + parent.left + r.right; - int bottom = tickerY + parent.top + r.bottom; - - if (posX > left && posX < right && posY > top && posY < bottom) { - v.performClick(); - playSoundEffect(SoundEffectConstants.CLICK); - if (mHapticFeedback) mVibrator.vibrate(25); - return true; - } - } - } - return false; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - - int index = event.getActionIndex(); - if (event.getActionMasked() == MotionEvent.ACTION_POINTER_UP - && index != 0 ) { - if (mCurrentNotficationEntry != null && mCurrentNotficationEntry.haloContent != null) { - Rect rootRect = new Rect(); - mHaloTickerContent.getHitRect(rootRect); - - PointF point = new PointF(); - getRawPoint(event, index, point); - browseView(point, rootRect, mCurrentNotficationEntry.haloContent); - } - } - return false; + updateResources(); } @Override @@ -1075,7 +983,7 @@ public void onConfigurationChanged(Configuration newConfiguration) { // This will reset the initialization flag mInitialized = false; // Generate a new content bubble - updateResources(mTickerLeft); + updateResources(); } @Override @@ -1086,59 +994,46 @@ protected void onLayout (boolean changed, int left, int top, int right, int bott } public void killTicker() { - flipContent(0, 0); tickerAnimator.animate(ObjectAnimator.ofFloat(this, "haloContentAlpha", 0f).setDuration(250), new DecelerateInterpolator(), null); } public void ticker(String tickerText, int delay, int startDuration) { - if (tickerText == null || tickerText.equals("")) { + if (tickerText == null || tickerText.isEmpty()) { killTicker(); return; } - flipContent(0, 0); - setHaloContentHeight((int)(mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height) * 0.6f)); - mHaloTickerContent.setVisibility(View.GONE); - mHaloTextView.setVisibility(View.VISIBLE); - mHaloTextView.setText(tickerText); - updateResources(mTickerLeft); + DisplayMetrics dpm = mContext.getResources().getDisplayMetrics(); + + int shrt = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, + mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_hpadding_short), dpm); + int wide = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_hpadding_wide), dpm); + int top = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_vpadding_top), dpm); + int bttm = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_vpadding_bottom), dpm); + + mHaloTextViewR.setText(tickerText); + mHaloTextViewR.setPadding(shrt, top, wide, bttm); + mHaloTextViewR.setGravity(Gravity.CENTER_HORIZONTAL); + mHaloTextViewR.setMaxLines(2); + mHaloTextViewL.setText(tickerText); + mHaloTextViewL.setPadding(wide, top, shrt, bttm); + mHaloTextViewL.setGravity(Gravity.CENTER_HORIZONTAL); + mHaloTextViewL.setMaxLines(2); float total = TICKER_HIDE_TIME + startDuration + 1000; PropertyValuesHolder tickerUpFrames = PropertyValuesHolder.ofKeyframe("haloContentAlpha", - Keyframe.ofFloat(0f, mHaloTextView.getAlpha()), - Keyframe.ofFloat(0.1f, 1f), - Keyframe.ofFloat(0.95f, 1f), + Keyframe.ofFloat(0f, mHaloTextViewL.getAlpha()), + Keyframe.ofFloat(startDuration / total, 1f), + Keyframe.ofFloat((TICKER_HIDE_TIME + startDuration) / total, 1f), Keyframe.ofFloat(1f, 0f)); tickerAnimator.animate(ObjectAnimator.ofPropertyValuesHolder(this, tickerUpFrames).setDuration((int)total), new DecelerateInterpolator(), null, delay, null); } - public void ticker(int delay, int startDuration, boolean flip) { - - setHaloContentHeight(mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height)); - mHaloTickerContent.setVisibility(View.VISIBLE); - mHaloTextView.setVisibility(View.GONE); - updateResources(mTickerLeft); - - if (startDuration != -1) { - // Finite tiker - float total = TICKER_HIDE_TIME + startDuration + 1000; - PropertyValuesHolder tickerUpFrames = PropertyValuesHolder.ofKeyframe("haloContentAlpha", - Keyframe.ofFloat(0f, mHaloTextView.getAlpha()), - Keyframe.ofFloat(0.1f, 1f), - Keyframe.ofFloat(0.95f, 1f), - Keyframe.ofFloat(1f, 0f)); - tickerAnimator.animate(ObjectAnimator.ofPropertyValuesHolder(this, tickerUpFrames).setDuration((int)total), - new DecelerateInterpolator(), null, delay, null); - } else { - // Infinite ticker (until killTicker() is called) - tickerAnimator.animate(ObjectAnimator.ofFloat(this, "haloContentAlpha", 1f).setDuration(250), - new DecelerateInterpolator(), null, delay, null); - } - if (flip) flipContent(500, delay); - } - public void ping(final Paint paint, final long delay) { if ((!mPingAllowed && paint != mPaintHoloRed) && mGesture != Gesture.TASK) return; @@ -1159,7 +1054,7 @@ public void run() { public void onAnimationUpdate(ValueAnimator animation) { pingRadius = (int)((pingMaxRadius - pingMinRadius) * animation.getAnimatedFraction()) + pingMinRadius; - postInvalidate(); + invalidate(); }}); // prevent ping spam @@ -1206,14 +1101,6 @@ public void nap(long delay) { public void run() { updateTriggerPosition(newPos, mHaloY); }}); - mHandler.postDelayed(new Runnable() { - public void run() { - if (mState != State.GESTURES && mState != State.DRAG) { - final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); - mEffect.animateHaloBatch(0, c, false, 3000, HaloProperties.MessageType.MESSAGE); - } - } - }, 2000); } public void sleep(long delay, int speed, final boolean silent) { @@ -1232,22 +1119,6 @@ public void unscheduleSleep() { } CustomObjectAnimator contentYAnimator = new CustomObjectAnimator(this); - public void slideContent(int duration, int y) { - contentYAnimator.animate(ObjectAnimator.ofInt(this, "HaloContentY", y).setDuration(duration), - new DecelerateInterpolator(), null); - } - - CustomObjectAnimator contentFlipAnimator = new CustomObjectAnimator(this); - public void flipContent(int duration, int delay) { - - // Make sure the animation does not stutter by letting it finish - if (contentFlipAnimator.isRunning()) return; - - contentFlipAnimator.animate(ObjectAnimator.ofFloat(mHaloTickerWrapper, "rotationY", - mTickerLeft ? -180 : 180, 0).setDuration(duration), new DecelerateInterpolator(), null, delay, null); - } - - int tickerX, tickerY; @Override protected void onDraw(Canvas canvas) { @@ -1259,16 +1130,15 @@ protected void onDraw(Canvas canvas) { } // Content - final int tickerHeight = mHaloTickerWrapper.getMeasuredHeight(); - int ch = mGesture == Gesture.TASK ? 0 : tickerHeight / 2; - int cw = mHaloTickerWrapper.getMeasuredWidth(); + state = canvas.save(); + int ch = mGesture == Gesture.TASK ? 0 : mHaloTickerContent.getMeasuredHeight() / 2; + int cw = mHaloTickerContent.getMeasuredWidth(); int y = mHaloY + mIconHalfSize - ch; - if (mGesture == Gesture.TASK) { if (mHaloY < mIconHalfSize) { - y = y + (int)(mIconSize * 0.20f); + y = y + (int)(mIconSize * 0.85f); } else { - y = y - mIconSize; + y = y - (int)(mIconSize * 0.85f); } } @@ -1277,6 +1147,20 @@ protected void onDraw(Canvas canvas) { x = mHaloX - cw - (int)(mIconSize * 0.1f); } + if (mState == State.DRAG) { + setHaloContentY(y); + } else { + if (y != getHaloContentY() && !contentYAnimator.isRunning()) { + contentYAnimator.animate(ObjectAnimator.ofInt(this, "HaloContentY", y).setDuration(300), + new DecelerateInterpolator(), null); + } + } + + state = canvas.save(); + canvas.translate(x, getHaloContentY()); + mHaloContentView.draw(canvas); + canvas.restoreToCount(state); + // X float fraction = 1 - ((float)xPaint.getAlpha()) / 255; int killyPos = (int)(mKillY - mBigRed.getWidth() / 2 - mIconSize * fraction); @@ -1284,16 +1168,14 @@ protected void onDraw(Canvas canvas) { // Horizontal Marker if (mGesture == Gesture.TASK) { - if (y > 0 && mNotificationData != null && getHaloMsgCount() > 0) { + if (y > 0 && mNotificationData != null && mNotificationData.size() > 0) { int pulseY = mHaloY + mIconHalfSize - mMarker.getHeight() / 2; - int items = getHaloMsgCount(); + int items = mNotificationData.size(); int indexLength = ((int)(mScreenWidth * 0.85f) - mIconSize) / items; - indexLength = indexLength > 120 ? 120 : indexLength; - for (int i = 0; i < items; i++) { - float pulseX = mTickerLeft ? (mIconSize * 1.3f + indexLength * i) - : (mScreenWidth - mIconSize * 1.3f - indexLength * i - mMarker.getWidth()); + float pulseX = mTickerLeft ? (mIconSize * 1.25f + indexLength * i) + : (mScreenWidth - mIconSize * 1.25f - indexLength * i - mMarker.getWidth()); boolean markerState = mTickerLeft ? mMarkerIndex >= 0 && i < items-mMarkerIndex : i <= mMarkerIndex; mMarkerPaint.setAlpha(markerState ? 255 : 100); canvas.drawBitmap(mMarker, pulseX, pulseY, mMarkerPaint); @@ -1322,37 +1204,12 @@ protected void onDraw(Canvas canvas) { canvas.drawBitmap(mMarkerB, xPos, yButtom, mMarkerPaint); } - if (mState == State.DRAG) { - setHaloContentY(y); - } else { - // Move content when ... - // 1. the calculated Y position is off - // 2. the content-animator is not running or we're in tasking state - if (y != getHaloContentY() && (!contentYAnimator.isRunning() || verticalGesture())) { - setHaloContentBackground(mTickerLeft, mGesture == Gesture.TASK && mHaloY > mIconHalfSize - ? HaloProperties.ContentStyle.CONTENT_DOWN : HaloProperties.ContentStyle.CONTENT_UP); - int duration = !verticalGesture() ? 300 : 0; - slideContent(duration, y); - flipContent(duration, 0); - } - } - - if (getHaloContentAlpha() > 0.0f) { - state = canvas.save(); - tickerX = x; - tickerY = getHaloContentY(); - canvas.translate(x, getHaloContentY()); - mHaloContentView.draw(canvas); - canvas.restoreToCount(state); - } - // Bubble state = canvas.save(); canvas.translate(mHaloX, mHaloY); mHaloBubble.draw(canvas); canvas.restoreToCount(state); - // Number if (mState == State.IDLE || mState == State.GESTURES) { state = canvas.save(); @@ -1381,18 +1238,15 @@ public WindowManager.LayoutParams getWMParams() { void clearTicker() { mEffect.mHaloIcon.setImageDrawable(null); mEffect.msgNumberAlphaAnimator.cancel(true); - mEffect.msgNumberFlipAnimator.cancel(true); - mEffect.tickerAnimator.cancel(true); mEffect.mHaloNumber.setAlpha(0f); - mEffect.mHaloNumberIcon.setAlpha(0f); mContentIntent = null; mCurrentNotficationEntry = null; mEffect.killTicker(); - mEffect.updateResources(mTickerLeft); + mEffect.updateResources(); mEffect.invalidate(); } - void tick(NotificationData.Entry entry, int delay, int duration, boolean alwaysFlip, boolean showContent, boolean flipContent) { + void tick(NotificationData.Entry entry, String text, int delay, int duration, boolean alwaysFlip) { if (entry == null) { clearTicker(); return; @@ -1408,38 +1262,14 @@ void tick(NotificationData.Entry entry, int delay, int duration, boolean alwaysF // set the avatar mEffect.mHaloIcon.setImageDrawable(new BitmapDrawable(mContext.getResources(), entry.getRoundIcon())); - if (showContent && mState != State.SILENT) { - if (entry.haloContent != null) { - try { - ((ViewGroup)mEffect.mHaloTickerContent).removeAllViews(); - ((ViewGroup)mEffect.mHaloTickerContent).addView(entry.haloContent); - mEffect.ticker(delay, duration, flipContent); - } catch(Exception e) { - // haloContent had a view already? Let's give it one last chance ... - try { - mBar.prepareHaloNotification(entry, notification, false); - if (entry.haloContent != null) ((ViewGroup)mEffect.mHaloTickerContent).addView(entry.haloContent); - mEffect.ticker(delay, duration, flipContent); - } catch(Exception ex) { - // Screw it, we're going with a simple text - mEffect.ticker(mNotificationText, delay, duration); - } - } - } - } + // Set text + if (mState != State.SILENT) mEffect.ticker(text, delay, duration); + mEffect.updateResources(); mEffect.invalidate(); // Set Number - HaloProperties.MessageType msgType; - if (entry.notification.getPackageName().equals("com.paranoid.halo")) { - msgType = HaloProperties.MessageType.PINNED; - } else if (!entry.notification.isClearable()) { - msgType = HaloProperties.MessageType.PINNED; - } else { - msgType = HaloProperties.MessageType.MESSAGE; - } - mEffect.animateHaloBatch(n.number, -1, alwaysFlip, delay, msgType); + mEffect.setHaloMessageNumber(n.number, alwaysFlip); } public void updateTicker(StatusBarNotification notification) { @@ -1455,182 +1285,43 @@ public void updateTicker(StatusBarNotification notification, String text) { } catch (android.os.RemoteException ex) { // System is dead } - if (allowed) { - for (int i = 0; i < mNotificationData.size(); i++) { - NotificationData.Entry entry = mNotificationData.get(i); - - if (entry.notification == notification) { - - // No intent, no tick ... - if (entry.notification.getNotification().contentIntent == null) return; - mIsNotificationNew = true; - if (mLastNotificationEntry != null && notification == mLastNotificationEntry.notification) { - // Ok, this is the same notification - // Let's give it a chance though, if the text has changed we allow it - mIsNotificationNew = !mNotificationText.equals(text); - } - - if (mIsNotificationNew) { - mNotificationText = text; - mLastNotificationEntry = entry; - - if (mState != State.FIRST_RUN) { - if (mState == State.IDLE || mState == State.HIDDEN) { - if (mState == State.HIDDEN) clearTicker(); - mEffect.wake(); - mEffect.nap(HaloEffect.NAP_DELAY + HaloEffect.WAKE_TIME * 2); - if (mHideTicker) mEffect.sleep(HaloEffect.SLEEP_DELAY + HaloEffect.WAKE_TIME * 2, HaloEffect.SLEEP_TIME, false); - } - - tick(entry, HaloEffect.WAKE_TIME * 2, 1000, true, true, false); - - // Pop while not tasking, only if notification is certified fresh - if (mGesture != Gesture.TASK && mState != State.SILENT) mEffect.ping(mPaintHoloBlue, HaloEffect.WAKE_TIME * 2); - } - } - break; - } - } - } - } - - public int getHaloMsgCount() { - int msgs = 0; - StatusBarNotification notification; - - for(int i = 0; i < mNotificationData.size(); i++) { - notification = mNotificationData.get(i).notification; - try { - if (!mNotificationManager.isPackageAllowedForHalo(notification.getPackageName())) continue; - } catch (android.os.RemoteException ex) { - // System is dead - } - msgs += 1; - } - return msgs; - } - - public int getHaloMsgIndex(int index, boolean notifyOnUnlock) { - int msgIndex = 0; - StatusBarNotification notification; - - for (int i = 0; i < mNotificationData.size(); i++){ - notification = mNotificationData.get(i).notification; - try { //ignore blacklisted notifications - if (!mNotificationManager.isPackageAllowedForHalo(notification.getPackageName())) continue; - } catch (android.os.RemoteException ex) { - // System is dead - } - //if notifying the user on unlock, ignore persistent notifications - if (notifyOnUnlock && !notification.isClearable()) continue; - - if (msgIndex == index) return i; - - msgIndex += 1; - } - return -1; - } - - public int getHidden() { - int ignore = 0; - boolean allowed = false; - boolean persistent = false; - - for (int i = 0; i < mNotificationData.size(); i++ ) { + for (int i = 0; i < mNotificationData.size(); i++) { NotificationData.Entry entry = mNotificationData.get(i); - StatusBarNotification statusNotify = entry.notification; - if (statusNotify == null) continue; - try { - allowed = mNotificationManager.isPackageAllowedForHalo(mNotificationData.get(i).notification.getPackageName()); - } catch (android.os.RemoteException ex) { - // System is dead - } - persistent = !mNotificationData.get(i).notification.isClearable(); - // persistent notifications that were not blacklisted and pinned apps - boolean hide = (statusNotify.getPackageName().equals("com.paranoid.halo") || (allowed && persistent)); - if (hide) ignore++; - } - return ignore; - } + if (entry.notification == notification) { - private class HaloReceiver extends INotificationListener.Stub { + // No intent, no tick ... + if (entry.notification.notification.contentIntent == null) return; - public HaloReceiver() { - } - - @Override - public void onNotificationPosted(StatusBarNotification notification) throws RemoteException { - } - - @Override - public void onNotificationRemoved(StatusBarNotification notification) throws RemoteException { - mHandler.postDelayed(new Runnable() { - public void run() { - // Find next entry - clearTicker(); - mEffect.clearAnimation(); - mNotificationText = ""; - NotificationData.Entry entry = null; - if (getHaloMsgCount() > 0) { - for (int i = getHaloMsgCount()-1; i >= 0; i--) { - NotificationData.Entry item = mNotificationData.get(getHaloMsgIndex(i, false)); - if (mCurrentNotficationEntry != null - && mCurrentNotficationEntry.notification == item.notification) { - continue; - } - if (item.notification.isClearable()) { - entry = item; - break; - } - } - } - // When no entry was found, take the last one - if (entry == null && getHaloMsgCount() > 0) { - loadLastNotification(false); - } else { - tick(entry, 0, 0, false, false, false); - } - final int c = getHaloMsgCount()-getHidden() < 0 ? 0 : getHaloMsgCount()-getHidden(); - mEffect.setHaloMessageNumber(c); - if (mState == State.IDLE) { - mEffect.nap(1500); - if (mHideTicker) mEffect.sleep(HaloEffect.NAP_TIME + 3000, HaloEffect.SLEEP_TIME, false); - } + mIsNotificationNew = true; + if (mLastNotificationEntry != null && notification == mLastNotificationEntry.notification) { + // Ok, this is the same notification + // Let's give it a chance though, if the text has changed we allow it + mIsNotificationNew = !mNotificationText.equals(text); } - }, mDismissDelay); - mDismissDelay = 100; - } - } + if (mIsNotificationNew) { + mNotificationText = text; + mLastNotificationEntry = entry; - public class ScreenReceiver extends BroadcastReceiver { + if (allowed && mState != State.FIRST_RUN) { + tick(entry, text, HaloEffect.WAKE_TIME, 1000, true); - @Override - public void onReceive(Context context, Intent intent) { - // When screen unlocked, HALO active & Expanded desktop mode, ping HALO and load last notification. - // Because notifications are not readily visible and HALO does not "tick" on protected lock screens - if(intent.getAction().equals(Intent.ACTION_USER_PRESENT) && - Settings.System.getInt(mContext.getContentResolver(), Settings.System.HALO_ACTIVE, 0) == 1) { - if (mKeyguardManager.isKeyguardSecure() || - (Settings.System.getInt(mContext.getContentResolver(), Settings.System.EXPANDED_DESKTOP_STATE, 0) == 1 && - mState == State.HIDDEN)) { - mEffect.animateHaloBatch(0, 0, false, 0, HaloProperties.MessageType.MESSAGE); - mHandler.postDelayed(new Runnable() { - public void run() { - int lastMsg = getHaloMsgCount() - getHidden(); - if (lastMsg > 0) { - NotificationData.Entry entry = mNotificationData.get(getHaloMsgIndex(lastMsg - 1, true)); - mEffect.wake(); - mEffect.nap(HaloEffect.NAP_DELAY + HaloEffect.WAKE_TIME * 2); - if (mHideTicker) mEffect.sleep(HaloEffect.SLEEP_DELAY + HaloEffect.WAKE_TIME * 2, HaloEffect.SLEEP_TIME, false); - tick(entry, HaloEffect.WAKE_TIME * 2, 1000, false, true, true); - mEffect.ping(mPaintHoloBlue, HaloEffect.WAKE_TIME * 2); - } + // Pop while not tasking, only if notification is certified fresh + if (mEnableColor) { + if (mGesture != Gesture.TASK && mState != State.SILENT) mEffect.ping(mPaintHoloCustom, HaloEffect.WAKE_TIME); + } else { + if (mGesture != Gesture.TASK && mState != State.SILENT) mEffect.ping(mPaintHolo, HaloEffect.WAKE_TIME); + } + if (mState == State.IDLE || mState == State.HIDDEN) { + mEffect.wake(); + mEffect.nap(HaloEffect.NAP_DELAY); + if (mHideTicker) mEffect.sleep(HaloEffect.SLEEP_DELAY, HaloEffect.SLEEP_TIME, false); + } } - }, 400); } + break; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java index 6c00f204a1a..e32bc3f0281 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/halo/HaloProperties.java @@ -24,10 +24,6 @@ import android.graphics.drawable.Drawable; import android.os.Handler; import android.provider.Settings; -import android.graphics.ColorFilter; -import android.graphics.PorterDuff; -import android.graphics.PorterDuff.Mode; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; @@ -58,25 +54,11 @@ public enum Overlay { MESSAGE } - public enum ContentStyle { - CONTENT_NONE, - CONTENT_DOWN, - CONTENT_UP - } - - public enum MessageType { - MESSAGE, - PINNED, - SYSTEM - } - - private Handler mAnimQueue = new Handler(); private LayoutInflater mInflater; protected int mHaloX = 0, mHaloY = 0; protected int mHaloContentY = 0; protected float mHaloContentAlpha = 0; - private int mHaloContentHeight = 0; private Drawable mHaloDismiss; private Drawable mHaloBackL; @@ -87,17 +69,13 @@ public enum MessageType { private Drawable mHaloSilenceR; private Drawable mHaloMessage; private Drawable mHaloCurrentOverlay; - private Drawable mHaloIconMessage; - private Drawable mHaloIconPersistent; - private Drawable mHaloIconPinned; - - protected Drawable mHaloSpeechL, mHaloSpeechR, mHaloSpeechLD, mHaloSpeechRD; protected View mHaloBubble; protected ImageView mHaloBg, mHaloBgCustom, mHaloIcon, mHaloOverlay; - protected View mHaloContentView, mHaloTickerContent, mHaloTickerWrapper; - protected TextView mHaloTextView; + protected View mHaloContentView, mHaloTickerContent; + protected TextView mHaloTextViewR, mHaloTextViewL; + protected RelativeLayout mHaloTickerContainer; protected View mHaloNumberView; protected TextView mHaloNumber; @@ -112,9 +90,6 @@ public enum MessageType { private Handler mHandler; private float mFraction = 1.0f; private int mHaloMessageNumber = 0; - private MessageType mHaloMessageType = MessageType.MESSAGE; - - private boolean mLastContentStateLeft = true; CustomObjectAnimator mHaloOverlayAnimator; @@ -132,17 +107,6 @@ public HaloProperties(Context context) { mHaloSilenceR = mContext.getResources().getDrawable(R.drawable.halo_silence_right); mHaloMessage = mContext.getResources().getDrawable(R.drawable.halo_message); - mHaloSpeechL = mContext.getResources().getDrawable(R.drawable.halo_speech_l_u); - mHaloSpeechR = mContext.getResources().getDrawable(R.drawable.halo_speech_r_u); - mHaloSpeechLD = mContext.getResources().getDrawable(R.drawable.halo_speech_l_d); - mHaloSpeechRD = mContext.getResources().getDrawable(R.drawable.halo_speech_r_d); - - mHaloIconMessage = mContext.getResources().getDrawable(R.drawable.halo_batch_message); - mHaloIconPersistent = mContext.getResources().getDrawable(R.drawable.halo_system_message); - mHaloIconPinned = mContext.getResources().getDrawable(R.drawable.halo_pinned_app); - - mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mHaloBubble = mInflater.inflate(R.layout.halo_bubble, null); mHaloBg = (ImageView) mHaloBubble.findViewById(R.id.halo_bg); mHaloBgCustom = (ImageView) mHaloBubble.findViewById(R.id.halo_bg_custom); @@ -150,18 +114,20 @@ public HaloProperties(Context context) { mHaloOverlay = (ImageView) mHaloBubble.findViewById(R.id.halo_overlay); mHaloContentView = mInflater.inflate(R.layout.halo_speech, null); - mHaloTickerWrapper = mHaloContentView.findViewById(R.id.ticker_wrapper); + mHaloTickerContainer = (RelativeLayout)mHaloContentView.findViewById(R.id.container); mHaloTickerContent = mHaloContentView.findViewById(R.id.ticker); - mHaloTextView = (TextView) mHaloContentView.findViewById(R.id.bubble); - mHaloTextView.setAlpha(1f); + mHaloTextViewR = (TextView) mHaloTickerContent.findViewById(R.id.bubble_r); + mHaloTextViewR.setAlpha(0f); + mHaloTextViewL = (TextView) mHaloTickerContent.findViewById(R.id.bubble_l); + mHaloTextViewL.setAlpha(0f); + + updateColorView(); mHaloNumberView = mInflater.inflate(R.layout.halo_number, null); mHaloNumberContainer = (RelativeLayout)mHaloNumberView.findViewById(R.id.container); mHaloNumber = (TextView) mHaloNumberView.findViewById(R.id.number); mHaloNumberIcon = (ImageView) mHaloNumberView.findViewById(R.id.icon); - mHaloNumberIcon.setImageDrawable(mHaloIconMessage); - - mHaloContentHeight = mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height); + mHaloNumberIcon.setImageDrawable(mContext.getResources().getDrawable(R.drawable.halo_batch_message)); mFraction = Settings.System.getFloat(mContext.getContentResolver(), Settings.System.HALO_SIZE, 1.0f); @@ -183,10 +149,16 @@ protected void onAttachedToWindow() { } } - int newPaddingHShort; - int newPaddingHWide; - int newPaddingVTop; - int newPaddingVBottom; + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + if (mAttached) { + mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); + mAttached = false; + } + } + public void setHaloSize(float fraction) { final int newBubbleSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_bubble_size) * fraction); @@ -196,30 +168,24 @@ public void setHaloSize(float fraction) { mHaloIcon.setLayoutParams(layoutParams); mHaloOverlay.setLayoutParams(layoutParams); - newPaddingHShort = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_hpadding_short) * fraction); - newPaddingHWide = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_hpadding_wide) * fraction); - newPaddingVTop = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_vpadding_top) * fraction); - newPaddingVBottom = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_vpadding_bottom) * fraction); - - final int newBatchSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_size) * fraction); - final int newBatchIconSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_icon_size) * fraction); + final int newNumberSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_size) * fraction); final int newNumberTextSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_text_size) * fraction); + RelativeLayout.LayoutParams layoutParams2 = new RelativeLayout.LayoutParams(newNumberSize, newNumberSize); + mHaloNumber.setLayoutParams(layoutParams2); + mHaloNumber.setTextSize(TypedValue.COMPLEX_UNIT_PX, newNumberTextSize); - LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(newBatchSize, newBatchSize); - mHaloNumberContainer.setLayoutParams(layoutParams2); + final int newSpeechTextSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_speech_text_size) * fraction); + mHaloTextViewR.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSpeechTextSize); + mHaloTextViewL.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSpeechTextSize); - RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(newBatchSize, newBatchSize); + final int newBatchIconSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_number_icon_size) * fraction); + RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(newBatchIconSize, newBatchIconSize); layoutParams3.addRule(RelativeLayout.CENTER_VERTICAL); layoutParams3.addRule(RelativeLayout.CENTER_HORIZONTAL); - mHaloNumber.setLayoutParams(layoutParams3); - mHaloNumber.setTextSize(TypedValue.COMPLEX_UNIT_PX, newNumberTextSize); - - RelativeLayout.LayoutParams layoutParams4 = new RelativeLayout.LayoutParams(newBatchIconSize, newBatchIconSize); - layoutParams4.addRule(RelativeLayout.CENTER_VERTICAL); - layoutParams4.addRule(RelativeLayout.CENTER_HORIZONTAL); - mHaloNumberIcon.setLayoutParams(layoutParams4); + mHaloNumberIcon.setLayoutParams(layoutParams3); - updateResources(mLastContentStateLeft); + updateResources(); + updateColorView(); } public void setHaloX(int value) { @@ -248,71 +214,38 @@ public int getHaloContentY() { protected CustomObjectAnimator msgNumberFlipAnimator = new CustomObjectAnimator(this); protected CustomObjectAnimator msgNumberAlphaAnimator = new CustomObjectAnimator(this); - public void animateHaloBatch(final int value, final int msgCount, final boolean alwaysFlip, int delay, final MessageType msgType) { - if (msgCount == 0) { - msgNumberAlphaAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "alpha", 0f).setDuration(1000), - new DecelerateInterpolator(), null, delay, null); - return; - } - mAnimQueue.removeCallbacksAndMessages(null); - mAnimQueue.postDelayed(new Runnable() { - public void run() { - // Allow transitions only if no overlay is set - if (mHaloCurrentOverlay == null) { - msgNumberAlphaAnimator.cancel(true); - float oldAlpha = mHaloNumberContainer.getAlpha(); - - mHaloNumberContainer.getBackground().clearColorFilter(); - mHaloNumberContainer.setAlpha(1f); - mHaloNumber.setAlpha(0f); - mHaloNumberIcon.setAlpha(0f); - - if (msgCount > 0) { - mHaloNumberContainer.getBackground().setColorFilter(0xff4fa736, PorterDuff.Mode.SRC_IN); - mHaloNumber.setText(String.valueOf(msgCount)); - mHaloNumber.setAlpha(1f); - } else if (value < 1 && msgCount < 1) { - if (msgType == MessageType.PINNED) { - mHaloNumberIcon.setImageDrawable(mHaloIconPinned); - } else if (msgType == MessageType.SYSTEM) { - mHaloNumberIcon.setImageDrawable(mHaloIconPersistent); - } else { - mHaloNumberIcon.setImageDrawable(mHaloIconMessage); - } - mHaloNumberIcon.setAlpha(1f); - } else if (value < 100) { - mHaloNumber.setText(String.valueOf(value)); - mHaloNumber.setAlpha(1f); - } else { - mHaloNumber.setText("+"); - mHaloNumber.setAlpha(1f); - } - - if (value < 1 && msgCount < 1) { - msgNumberAlphaAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "alpha", 0f).setDuration(1000), - new DecelerateInterpolator(), null, 1500, null); - } - - // Do NOT flip when ... - if (!alwaysFlip && oldAlpha == 1f && mHaloMessageType == msgType - && (value == mHaloMessageNumber || (value > 99 && mHaloMessageNumber > 99))) return; - - msgNumberFlipAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "rotationY", -180, 0).setDuration(500), - new DecelerateInterpolator(), null); - } - mHaloMessageNumber = value; - mHaloMessageType = msgType; - }}, delay); - } + public void setHaloMessageNumber(int value, boolean alwaysFlip) { + + // Allow transitions only if no overlay is set + if (mHaloCurrentOverlay == null) { + msgNumberAlphaAnimator.cancel(true); + float oldAlpha = mHaloNumberContainer.getAlpha(); + + mHaloNumberContainer.setAlpha(1f); + mHaloNumber.setAlpha(1f); + mHaloNumberIcon.setAlpha(0f); + if (value < 1) { + mHaloNumber.setText(""); + mHaloNumberIcon.setAlpha(1f); + } else if (value < 100) { + mHaloNumber.setText(String.valueOf(value)); + } else { + mHaloNumber.setText("+"); + } + + if (value < 1) { + msgNumberAlphaAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "alpha", 0f).setDuration(1000), + new DecelerateInterpolator(), null, 1500, null); + } - void setHaloMessageNumber(int count) { - mHaloNumber.setText(String.valueOf(count)); - invalidate(); + if (!alwaysFlip && oldAlpha == 1f && (value == mHaloMessageNumber || (value > 99 && mHaloMessageNumber > 99))) return; + msgNumberFlipAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "rotationY", -180, 0).setDuration(500), + new DecelerateInterpolator(), null); + } + mHaloMessageNumber = value; } public void setHaloContentAlpha(float value) { - mHaloTickerWrapper.setAlpha(value); - mHaloTickerWrapper.invalidate(); mHaloContentAlpha = value; mHaloTextViewL.setAlpha(value); mHaloTextViewR.setAlpha(value); @@ -363,60 +296,24 @@ public void setHaloOverlay(Overlay overlay, float overlayAlpha) { // Fade out number batch if (overlay != Overlay.NONE) { - msgNumberAlphaAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "alpha", 0f).setDuration(100), + msgNumberFlipAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "rotationY", 270).setDuration(500), + new DecelerateInterpolator(), null); + msgNumberAlphaAnimator.animate(ObjectAnimator.ofFloat(mHaloNumberContainer, "alpha", 0f).setDuration(500), new DecelerateInterpolator(), null); } } mHaloOverlay.setAlpha(overlayAlpha); - updateResources(mLastContentStateLeft); + updateResources(); } - private ContentStyle mLastContentStyle = ContentStyle.CONTENT_NONE; - public void setHaloContentBackground(boolean contentLeft, ContentStyle style) { - if (contentLeft != mLastContentStateLeft || style != mLastContentStyle) { - // Set background - switch(style) { - case CONTENT_UP: - mHaloTickerWrapper.setBackground(contentLeft ? mHaloSpeechL : mHaloSpeechR); - break; - case CONTENT_DOWN: - mHaloTickerWrapper.setBackground(contentLeft ? mHaloSpeechLD : mHaloSpeechRD); - break; - } + public void updateResources() { - // ... and override its padding - if (contentLeft) { - mHaloTickerWrapper.setPadding(newPaddingHWide, newPaddingVTop, newPaddingHShort, newPaddingVBottom); - } else { - mHaloTickerWrapper.setPadding(newPaddingHShort, newPaddingVTop, newPaddingHWide, newPaddingVBottom); - } - - mLastContentStyle = style; - } - } - - public void setHaloContentHeight(int size) { - mHaloContentHeight = size; - } - - public void updateResources(boolean contentLeft) { - android.util.Log.d("PARANOID", "-- updateResources"); - - // Maximal stretch for speech bubble, wrap_content regular text - final boolean portrait = getWidth() < getHeight(); final int iconSize = (int)(mContext.getResources().getDimensionPixelSize(R.dimen.halo_bubble_size) * mFraction); - int portraitWidth = portrait ? ((int)(getWidth() * 0.95f) - iconSize) : ((int)(getHeight() * 0.95f)); - if (mHaloTextView.getVisibility() == View.VISIBLE) portraitWidth = LinearLayout.LayoutParams.WRAP_CONTENT; - - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - portraitWidth, mHaloContentHeight); - mHaloTickerWrapper.setLayoutParams(layoutParams); + final int newSize = (int)(getWidth() * 0.9f) - iconSize; + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(newSize, LinearLayout.LayoutParams.WRAP_CONTENT); + mHaloTickerContainer.setLayoutParams(layoutParams); - // Set background and override its padding - setHaloContentBackground(contentLeft, mLastContentStyle); - - // Measure controls mHaloContentView.measure(MeasureSpec.getSize(mHaloContentView.getMeasuredWidth()), MeasureSpec.getSize(mHaloContentView.getMeasuredHeight())); mHaloContentView.layout(0, 0, 0, 0); @@ -428,8 +325,6 @@ public void updateResources(boolean contentLeft) { mHaloNumberView.measure(MeasureSpec.getSize(mHaloNumberView.getMeasuredWidth()), MeasureSpec.getSize(mHaloNumberView.getMeasuredHeight())); mHaloNumberView.layout(0, 0, 0, 0); - - mLastContentStateLeft = contentLeft; } class SettingsObserver extends ContentObserver {