From 01d870590b3f1ee272c49db743d82fbdc6e98913 Mon Sep 17 00:00:00 2001 From: Carlo Savignano Date: Sun, 23 Oct 2016 18:41:27 +0800 Subject: [PATCH 01/51] pocket: introduce pocket judge/lock * Judge if device is in pocket. * Notify clients callbacks when pocked state changes. * Start listening when device becomes not interactive. * Stop listening when device becomes interactive and is NOT in pocket. Ticket: NOUGAT-9. Signed-off-by: Carlo Savignano Signed-off-by: Alex Naidis Squashed commits: commit a712df9f2569ff72f4fb9c42adda472df5f2d4c4 Author: jhenrique09 Date: Sat Sep 12 11:55:04 2020 -0300 Pocket Lock: Don't show immersive confirmation ui Change-Id: I7de7cda0a1482ef7ef107cd69a28ac80b9f747d4 commit 586a00f09d668ab4cb300b6dcb10c0965cd0a156 Author: jhenrique09 Date: Tue Sep 8 09:44:29 2020 -0300 PocketLock: fix flickering on animations Change-Id: I4b5499042d0e9ae8f73ecf5c32030d146f640362 commit d4b16d04f61d0a68f73172db2105259b5350a199 Author: RadixCube Date: Sun Jun 2 18:14:51 2019 +0000 pocket: Reduce sleep timeout for pocket lock *if the proximity value changes within 10s, pocketlock exits to lockscreen. Inorder to avoid that reduce timeout to 3s Change-Id: Ie233f17d59c0383538a0e8cb71707c07010fc905 commit be8b1515dfacce20b1ea2656d5aacc29f1dd4685 Author: paphonb Date: Sat Jun 8 08:37:35 2019 +0000 Fix an edge case in KeyguardUpdateMonitor pocket callback Change-Id: I7489d1fbda5622d6bff72b9a1c27e35becaa3eb1 commit 9addd6201ecebcaae108583f9c3212e4a56c4ae8 Author: Henrique Silva Date: Thu May 2 16:35:09 2019 -0300 Pocket lock improvements * Fix auto hide not working correctly * Restore systemui visibility when hidden Change-Id: I2bb57b56cdf431d32cdbc3c67f272bf982518884 commit fd6c2dd9934265119be3c7ffd0f9bd082b25d1d6 Author: TheStrix Date: Wed Mar 6 20:02:08 2019 +0530 pocket: Fix pocket lock view for display cutouts - Use LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES layout flag to extend pocket lock view for display cutout mode. Change-Id: I21e4e47cf999b3a0f3d6ebf9165ba9f5596ece0e commit cf5e15aa099036988258cdfbdf6a39c80249d0a0 Author: TheStrix Date: Wed Mar 6 14:40:06 2019 +0530 pocket: Adjust sleep timeout for pocket lock view to 10 secs - Fix the case where user sets a high value for sleep timeout in display settings and the pocket view is also displayed for that much duration. Change-Id: If6c4daa1fd98992141f22db70e0e86d5d990f789 commit 3ccc78d41b42a8a37dd17b76c1e22179ab6df557 Author: Chris Lahaye Date: Tue Apr 25 00:10:35 2017 +0200 pocket: introduce pocket bridge This service communicates pocket state to the pocket judge kernel driver. It maintains the pocket state by binding to the pocket service. Ticket: NOUGAT-49 Change-Id: Iee77f767f23d3f77a0d1d871f9305f3b3c6d6630 Signed-off-by: Chris Lahaye Signed-off-by: Alex Naidis commit 11a523c5091037445e35cbac91d2313354dbc875 Author: Alex Naidis Date: Mon Aug 14 20:56:16 2017 -0400 PocketService: Adjust light sensor rate to 400ms We already adjusted the proximity sensor rate to 400ms, so adjust the rate for the light sensor accordingly and create a tunable. Change-Id: Ie6dda80df8cdc677eb6cdb873a5ce1e888572fe7 Signed-off-by: Alex Naidis commit 5650e0db14c74921c02db899894281dafc2c6d0d Author: Chris Lahaye Date: Tue Sep 26 19:19:19 2017 +0200 pocket: Add hardware acceleration and properly maintain SYSTEM_UI flags Change-Id: I585598242beec34bd92c5df5836ab395b36cea05 commit f73d036f1da30fa9fa4b9b872f80254886b1bc41 Author: Carlo Savignano Date: Tue Oct 25 18:45:47 2016 +0800 policy: introduce pocket lock * Block touch screen and keys inputs when device is in pocket. * Safe-door to disable pocket lock within long press power button if sensors do not behave correctly after PocketManager.isDeviceInPocket() returns true. * Window uses TYPE_SYSTEM_ERROR flag with ensure high priority over the lockscreen and other high priority windows. * Do not illuminate buttons when pocket lock is showing. * Disable fingerprint events and gestures when in pocket * Be friendly towards Keypress Boost Contributors: Carlo Savignano Chris Lahaye Anas Karbila Alex Naidis Park Ju Hyung Ticket: NOUGAT-15 Change-Id: I21e121c03a978fc2a0640d98a9d693a3e9812e2b Signed-off-by: Carlo Savignano Signed-off-by: Alex Naidis Signed-off-by: jhenrique09 Change-Id: I5d5cc35a98381e5b7030c384fda4df348e32361a --- CleanSpec.mk | 1 + .../android/app/SystemServiceRegistry.java | 11 + core/java/android/content/Context.java | 10 + core/java/android/pocket/IPocketCallback.aidl | 24 + core/java/android/pocket/IPocketService.aidl | 43 + core/java/android/pocket/PocketConstants.java | 25 + core/java/android/pocket/PocketManager.java | 233 ++++++ core/java/android/provider/Settings.java | 10 + core/java/android/view/View.java | 7 + .../res/layout/pocket_lock_view_layout.xml | 42 + core/res/res/values/custom_config.xml | 5 +- core/res/res/values/custom_strings.xml | 3 + core/res/res/values/custom_symbols.xml | 9 +- .../validators/SystemSettingsValidators.java | 1 + .../keyguard/KeyguardUpdateMonitor.java | 38 +- .../server/pocket/PocketBridgeService.java | 177 +++++ .../android/server/pocket/PocketService.java | 751 ++++++++++++++++++ .../server/policy/PhoneWindowManager.java | 180 ++++- .../server/policy/pocket/PocketLock.java | 198 +++++ .../com/android/server/wm/DisplayPolicy.java | 3 +- .../java/com/android/server/SystemServer.java | 14 + 21 files changed, 1763 insertions(+), 22 deletions(-) create mode 100644 core/java/android/pocket/IPocketCallback.aidl create mode 100644 core/java/android/pocket/IPocketService.aidl create mode 100644 core/java/android/pocket/PocketConstants.java create mode 100644 core/java/android/pocket/PocketManager.java create mode 100644 core/res/res/layout/pocket_lock_view_layout.xml create mode 100644 services/core/java/com/android/server/pocket/PocketBridgeService.java create mode 100644 services/core/java/com/android/server/pocket/PocketService.java create mode 100644 services/core/java/com/android/server/policy/pocket/PocketLock.java diff --git a/CleanSpec.mk b/CleanSpec.mk index 02e8eecbb72..e8ab07d6460 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -78,6 +78,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/symbols/system/lib/libhwui.so) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libhwui.so) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/storage/*) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/content/IClipboard.P) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/pocket/*) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/android/internal/telephony/ITelephonyRegistry.P) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/docs/api-stubs*) diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 5e0913aaa30..0dc4a061012 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -173,6 +173,8 @@ import android.os.storage.StorageManager; import android.permission.PermissionControllerManager; import android.permission.PermissionManager; +import android.pocket.IPocketService; +import android.pocket.PocketManager; import android.print.IPrintManager; import android.print.PrintManager; import android.security.FileIntegrityManager; @@ -943,6 +945,15 @@ public DcDimmingManager createService(ContextImpl ctx) throws ServiceNotFoundExc return new DcDimmingManager(service); }}); + registerService(Context.POCKET_SERVICE, PocketManager.class, + new CachedServiceFetcher() { + @Override + public PocketManager createService(ContextImpl ctx) { + IBinder binder = ServiceManager.getService(Context.POCKET_SERVICE); + IPocketService service = IPocketService.Stub.asInterface(binder); + return new PocketManager(ctx.getOuterContext(), service); + }}); + registerService(Context.TV_INPUT_SERVICE, TvInputManager.class, new CachedServiceFetcher() { @Override diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index e0d2d45f125..de289df53ca 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -5086,6 +5086,16 @@ public abstract boolean startInstrumentation(@NonNull ComponentName className, */ public static final String DYNAMIC_SYSTEM_SERVICE = "dynamic_system"; + /** + * Use with {@link #getSystemService} to retrieve a + * {@link android.os.PocketManager} for accessing and listening to device pocket state. + * + * @hide + * @see #getSystemService + * @see android.os.PocketManager + */ + public static final String POCKET_SERVICE = "pocket"; + /** * Use with {@link #getSystemService(String)} to retrieve a {@link * android.app.blob.BlobStoreManager} for contributing and accessing data blobs diff --git a/core/java/android/pocket/IPocketCallback.aidl b/core/java/android/pocket/IPocketCallback.aidl new file mode 100644 index 00000000000..53e5412f89b --- /dev/null +++ b/core/java/android/pocket/IPocketCallback.aidl @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2016 The ParanoidAndroid Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.pocket; + +/** @hide */ +interface IPocketCallback { + + // notify when pocket state changes. + void onStateChanged(boolean isDeviceInPocket, int reason); + +} \ No newline at end of file diff --git a/core/java/android/pocket/IPocketService.aidl b/core/java/android/pocket/IPocketService.aidl new file mode 100644 index 00000000000..78346577420 --- /dev/null +++ b/core/java/android/pocket/IPocketService.aidl @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2016 The ParanoidAndroid Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.pocket; + +import android.pocket.IPocketCallback; + +/** @hide */ +interface IPocketService { + + // add callback to get notified about pocket state. + void addCallback(IPocketCallback callback); + + // remove callback and stop getting notified about pocket state. + void removeCallback(IPocketCallback callback); + + // notify pocket service about intercative state changed. + // @see com.android.policy.PhoneWindowManager + void onInteractiveChanged(boolean interactive); + + // external processes can request changing listening state. + void setListeningExternal(boolean listen); + + // check if device is in pocket. + boolean isDeviceInPocket(); + + // Custom methods + void setPocketLockVisible(boolean visible); + boolean isPocketLockVisible(); + +} \ No newline at end of file diff --git a/core/java/android/pocket/PocketConstants.java b/core/java/android/pocket/PocketConstants.java new file mode 100644 index 00000000000..f0d08a27237 --- /dev/null +++ b/core/java/android/pocket/PocketConstants.java @@ -0,0 +1,25 @@ +package android.pocket; + +/** + * This class contains global pocket setup constants. + * @author Carlo Savignano + * @hide + */ + +public class PocketConstants { + + public static final boolean DEBUG = false; + public static final boolean DEBUG_SPEW = false; + + /** + * Whether to use proximity sensor to evaluate pocket state. + */ + public static final boolean ENABLE_PROXIMITY_JUDGE = true; + + /** + * Whether to use light sensor to evaluate pocket state. + */ + public static final boolean ENABLE_LIGHT_JUDGE = true; + + +} diff --git a/core/java/android/pocket/PocketManager.java b/core/java/android/pocket/PocketManager.java new file mode 100644 index 00000000000..22b60696289 --- /dev/null +++ b/core/java/android/pocket/PocketManager.java @@ -0,0 +1,233 @@ +/** + * Copyright (C) 2016 The ParanoidAndroid Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.pocket; + +import android.content.Context; +import android.os.Handler; +import android.os.PowerManager; +import android.os.RemoteException; +import android.os.SystemClock; +import android.text.format.DateUtils; +import android.util.Log; +import android.util.Slog; + +/** + * A class that coordinates listening for pocket state. + *

+ * Use {@link android.content.Context#getSystemService(java.lang.String)} + * with argument {@link android.content.Context#POCKET_SERVICE} to get + * an instance of this class. + * + * Usage: import and create a final {@link IPocketCallback.Stub()} and implement your logic in + * {@link IPocketCallback#onStateChanged(boolean, int)}. Then add your callback to the pocket manager + * + * // define a final callback + * private final IPocketCallback mCallback = new IPocketCallback.Stub() { + * + * @Override + * public void onStateChanged(boolean isDeviceInPocket, int reason) { + * // Your method to handle logic outside of this callback, ideally with a handler + * // posting on UI Thread for view hierarchy operations or with its own background thread. + * handlePocketStateChanged(isDeviceInPocket, reason); + * } + * + * } + * + * // add callback to pocket manager + * private void addCallback() { + * PocketManager manager = (PocketManager) context.getSystemService(Context.POCKET_SERVICE); + * manager.addCallback(mCallback); + * } + * + * @author Carlo Savignano + * @hide + */ +public class PocketManager { + + private static final String TAG = PocketManager.class.getSimpleName(); + static final boolean DEBUG = false; + + /** + * Whether {@link IPocketCallback#onStateChanged(boolean, int)} + * was fired because of the sensor. + * @see PocketService#handleDispatchCallbacks() + */ + public static final int REASON_SENSOR = 0; + + /** + * Whether {@link IPocketCallback#onStateChanged(boolean, int)} + * was fired because of an error while accessing service. + * @see #addCallback(IPocketCallback) + * @see #removeCallback(IPocketCallback) + */ + public static final int REASON_ERROR = 1; + + /** + * Whether {@link IPocketCallback#onStateChanged(boolean, int)} + * was fired because of a needed reset. + * @see PocketService#binderDied() + */ + public static final int REASON_RESET = 2; + + private Context mContext; + private IPocketService mService; + private PowerManager mPowerManager; + private Handler mHandler; + private boolean mPocketViewTimerActive; + + public PocketManager(Context context, IPocketService service) { + mContext = context; + mService = service; + if (mService == null) { + Slog.v(TAG, "PocketService was null"); + } + mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mHandler = new Handler(); + } + + /** + * Add pocket state callback. + * @see PocketService#handleRemoveCallback(IPocketCallback) + */ + public void addCallback(final IPocketCallback callback) { + if (mService != null) try { + mService.addCallback(callback); + } catch (RemoteException e1) { + Log.w(TAG, "Remote exception in addCallback: ", e1); + if (callback != null){ + try { + callback.onStateChanged(false, REASON_ERROR); + } catch (RemoteException e2) { + Log.w(TAG, "Remote exception in callback.onPocketStateChanged: ", e2); + } + } + } + } + + /** + * Remove pocket state callback. + * @see PocketService#handleAddCallback(IPocketCallback) + */ + public void removeCallback(final IPocketCallback callback) { + if (mService != null) try { + mService.removeCallback(callback); + } catch (RemoteException e1) { + Log.w(TAG, "Remote exception in removeCallback: ", e1); + if (callback != null){ + try { + callback.onStateChanged(false, REASON_ERROR); + } catch (RemoteException e2) { + Log.w(TAG, "Remote exception in callback.onPocketStateChanged: ", e2); + } + } + } + } + + /** + * Notify service about device interactive state changed. + * {@link PhoneWindowManager#startedWakingUp()} + * {@link PhoneWindowManager#startedGoingToSleep(int)} + */ + public void onInteractiveChanged(boolean interactive) { + boolean isPocketViewShowing = (interactive && isDeviceInPocket()); + synchronized (mPocketLockTimeout) { + if (mPocketViewTimerActive != isPocketViewShowing) { + if (isPocketViewShowing) { + if (DEBUG) Log.v(TAG, "Setting pocket timer"); + mHandler.removeCallbacks(mPocketLockTimeout); // remove any pending requests + mHandler.postDelayed(mPocketLockTimeout, 3 * DateUtils.SECOND_IN_MILLIS); + mPocketViewTimerActive = true; + } else { + if (DEBUG) Log.v(TAG, "Clearing pocket timer"); + mHandler.removeCallbacks(mPocketLockTimeout); + mPocketViewTimerActive = false; + } + } + } + if (mService != null) try { + mService.onInteractiveChanged(interactive); + } catch (RemoteException e) { + Log.w(TAG, "Remote exception in addCallback: ", e); + } + } + + /** + * Request listening state change by, but not limited to, external process. + * @see PocketService#handleSetListeningExternal(boolean) + */ + public void setListeningExternal(boolean listen) { + if (mService != null) try { + mService.setListeningExternal(listen); + } catch (RemoteException e) { + Log.w(TAG, "Remote exception in setListeningExternal: ", e); + } + // Clear timeout when user hides pocket lock with long press power. + if (mPocketViewTimerActive && !listen) { + if (DEBUG) Log.v(TAG, "Clearing pocket timer due to override"); + mHandler.removeCallbacks(mPocketLockTimeout); + mPocketViewTimerActive = false; + } + } + + /** + * Return whether device is in pocket. + * @see PocketService#isDeviceInPocket() + * @return + */ + public boolean isDeviceInPocket() { + if (mService != null) try { + return mService.isDeviceInPocket(); + } catch (RemoteException e) { + Log.w(TAG, "Remote exception in isDeviceInPocket: ", e); + } + return false; + } + + class PocketLockTimeout implements Runnable { + @Override + public void run() { + mPowerManager.goToSleep(SystemClock.uptimeMillis()); + mPocketViewTimerActive = false; + } + } + + /** Custom methods **/ + + public void setPocketLockVisible(boolean visible) { + if (!visible){ + if (DEBUG) Log.v(TAG, "Clearing pocket timer"); + mHandler.removeCallbacks(mPocketLockTimeout); + mPocketViewTimerActive = false; + } + if (mService != null) try { + mService.setPocketLockVisible(visible); + } catch (RemoteException e) { + Log.w(TAG, "Remote exception in setPocketLockVisible: ", e); + } + } + + public boolean isPocketLockVisible() { + if (mService != null) try { + return mService.isPocketLockVisible(); + } catch (RemoteException e) { + Log.w(TAG, "Remote exception in isPocketLockVisible: ", e); + } + return false; + } + + private PocketLockTimeout mPocketLockTimeout = new PocketLockTimeout(); + +} diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index a1d5dd1e31f..8b2fed10218 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5733,6 +5733,15 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean */ public static final String QS_SHOW_BATTERY_PERCENT = "qs_header_show_battery_percent"; + /** + * Whether allowing pocket service to register sensors and dispatch informations. + * 0 = disabled + * 1 = enabled + * @author Carlo Savignano + * @hide + */ + public static final String POCKET_JUDGE = "pocket_judge"; + /** * Battery style * @hide @@ -5945,6 +5954,7 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean PRIVATE_SETTINGS.add(AUTO_ACCENT_TYPE); PRIVATE_SETTINGS.add(SYSTEMUI_PLUGIN_VOLUME); PRIVATE_SETTINGS.add(QS_SHOW_BATTERY_PERCENT); + PRIVATE_SETTINGS.add(POCKET_JUDGE); } /** diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index ca424e79ed7..e3a220706b0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3843,6 +3843,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @Deprecated public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010; + /** + * @hide + * + * Pocket lock + */ + public static final int SYSTEM_UI_FLAG_POCKET_LOCK = 0x00000020; + /** * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead. */ diff --git a/core/res/res/layout/pocket_lock_view_layout.xml b/core/res/res/layout/pocket_lock_view_layout.xml new file mode 100644 index 00000000000..2eca671011d --- /dev/null +++ b/core/res/res/layout/pocket_lock_view_layout.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + diff --git a/core/res/res/values/custom_config.xml b/core/res/res/values/custom_config.xml index 3cc0d2a72e3..4d132ee7912 100644 --- a/core/res/res/values/custom_config.xml +++ b/core/res/res/values/custom_config.xml @@ -213,5 +213,8 @@ - + + + diff --git a/core/res/res/values/custom_strings.xml b/core/res/res/values/custom_strings.xml index c79757d71c6..57c6f7b2f77 100644 --- a/core/res/res/values/custom_strings.xml +++ b/core/res/res/values/custom_strings.xml @@ -49,4 +49,7 @@ SystemUI restart required For all changes to take effect, a SystemUI restart is required. Restart SystemUI now? + + + Press and hold power button to unlock diff --git a/core/res/res/values/custom_symbols.xml b/core/res/res/values/custom_symbols.xml index 57a35deff47..5aa021d1dcd 100644 --- a/core/res/res/values/custom_symbols.xml +++ b/core/res/res/values/custom_symbols.xml @@ -149,5 +149,12 @@ - + + + + + + + + diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java index 92757dcdb46..f7bcfa84deb 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java @@ -258,5 +258,6 @@ public boolean validate(String value) { }); VALIDATORS.put(System.FOD_GESTURE, BOOLEAN_VALIDATOR); VALIDATORS.put(System.ACCENT_COLOR, ANY_INTEGER_VALIDATOR); + VALIDATORS.put(System.POCKET_JUDGE, BOOLEAN_VALIDATOR); } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 33061f0bbda..14029eafc52 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -69,6 +69,8 @@ import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; +import android.pocket.IPocketCallback; +import android.pocket.PocketManager; import android.provider.Settings; import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; @@ -183,6 +185,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private static final int MSG_USER_REMOVED = 341; private static final int MSG_KEYGUARD_GOING_AWAY = 342; + // Additional messages should be 600+ + private static final int MSG_POCKET_STATE_CHANGED = 600; + /** Biometric authentication state: Not listening. */ private static final int BIOMETRIC_STATE_STOPPED = 0; @@ -328,6 +333,27 @@ public void onChanged(Integer ringer) { } }; + private PocketManager mPocketManager; + private boolean mIsDeviceInPocket; + private final IPocketCallback mPocketCallback = new IPocketCallback.Stub() { + @Override + public void onStateChanged(boolean isDeviceInPocket, int reason) { + boolean wasInPocket = mIsDeviceInPocket; + if (reason == PocketManager.REASON_SENSOR) { + mIsDeviceInPocket = isDeviceInPocket; + } else { + mIsDeviceInPocket = false; + } + if (wasInPocket != mIsDeviceInPocket) { + mHandler.sendEmptyMessage(MSG_POCKET_STATE_CHANGED); + } + } + }; + + public boolean isPocketLockVisible(){ + return mPocketManager.isPocketLockVisible(); + } + private SparseBooleanArray mFaceSettingEnabledForUser = new SparseBooleanArray(); private BiometricManager mBiometricManager; private IBiometricEnabledOnKeyguardCallback mBiometricEnabledCallback = @@ -1707,6 +1733,9 @@ public void handleMessage(Message msg) { case MSG_KEYGUARD_GOING_AWAY: handleKeyguardGoingAway((boolean) msg.obj); break; + case MSG_POCKET_STATE_CHANGED: + updateFingerprintListeningState(); + break; default: super.handleMessage(msg); break; @@ -1788,6 +1817,11 @@ public void handleMessage(Message msg) { mDreamManager = IDreamManager.Stub.asInterface( ServiceManager.getService(DreamService.DREAM_SERVICE)); + mPocketManager = (PocketManager) context.getSystemService(Context.POCKET_SERVICE); + if (mPocketManager != null) { + mPocketManager.addCallback(mPocketCallback); + } + if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE); } @@ -1973,14 +2007,14 @@ private boolean shouldListenForFingerprint() { (mKeyguardOccluded && mIsDreaming)) && mDeviceInteractive && !mGoingToSleep && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser()) && (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser - && allowedOnBouncer; + && allowedOnBouncer && !mIsDeviceInPocket; } else { return (mKeyguardIsVisible || !mDeviceInteractive || (mBouncer && !mKeyguardGoingAway) || mGoingToSleep || shouldListenForFingerprintAssistant() || (mKeyguardOccluded && mIsDreaming)) && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser()) && (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser - && allowedOnBouncer; + && allowedOnBouncer && !mIsDeviceInPocket; } } diff --git a/services/core/java/com/android/server/pocket/PocketBridgeService.java b/services/core/java/com/android/server/pocket/PocketBridgeService.java new file mode 100644 index 00000000000..f57bf054036 --- /dev/null +++ b/services/core/java/com/android/server/pocket/PocketBridgeService.java @@ -0,0 +1,177 @@ +/** + * Copyright (C) 2017 The ParanoidAndroid Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.pocket; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; + +import android.content.Context; +import android.database.ContentObserver; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.Process; +import android.os.UserHandle; +import android.pocket.IPocketCallback; +import android.pocket.PocketManager; +import android.provider.Settings.System; +import android.util.Slog; +import com.android.internal.util.FastPrintWriter; +import com.android.server.SystemService; + +import static android.provider.Settings.System.POCKET_JUDGE; + +/** + * This service communicates pocket state to the pocket judge kernel driver. + * It maintains the pocket state by binding to the pocket service. + * + * @author Chris Lahaye + * @hide + */ +public class PocketBridgeService extends SystemService { + + private static final String TAG = PocketBridgeService.class.getSimpleName(); + private static final int MSG_POCKET_STATE_CHANGED = 1; + + private Context mContext; + private boolean mEnabled; + private PocketBridgeHandler mHandler; + private PocketBridgeObserver mObserver; + + private PocketManager mPocketManager; + private boolean mIsDeviceInPocket; + private final IPocketCallback mPocketCallback = new IPocketCallback.Stub() { + @Override + public void onStateChanged(boolean isDeviceInPocket, int reason) { + boolean changed = false; + if (reason == PocketManager.REASON_SENSOR) { + if (isDeviceInPocket != mIsDeviceInPocket) { + mIsDeviceInPocket = isDeviceInPocket; + changed = true; + } + } else { + changed = isDeviceInPocket != mIsDeviceInPocket; + mIsDeviceInPocket = false; + } + if (changed) { + mHandler.sendEmptyMessage(MSG_POCKET_STATE_CHANGED); + } + } + }; + + public PocketBridgeService(Context context) { + super(context); + mContext = context; + HandlerThread handlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND); + handlerThread.start(); + mHandler = new PocketBridgeHandler(handlerThread.getLooper()); + mPocketManager = (PocketManager) + context.getSystemService(Context.POCKET_SERVICE); + mObserver = new PocketBridgeObserver(mHandler); + mObserver.onChange(true); + mObserver.register(); + } + + @Override + public void onStart() { + } + + private void setEnabled(boolean enabled) { + if (enabled != mEnabled) { + mEnabled = enabled; + update(); + } + } + + private void update() { + if (mPocketManager == null) return; + + if (mEnabled) { + mPocketManager.addCallback(mPocketCallback); + } else { + mPocketManager.removeCallback(mPocketCallback); + } + } + + private class PocketBridgeHandler extends Handler { + + private FileOutputStream mFileOutputStream; + private FastPrintWriter mPrintWriter; + + public PocketBridgeHandler(Looper looper) { + super(looper); + + try { + mFileOutputStream = new FileOutputStream( + mContext.getResources().getString( + com.android.internal.R.string.config_pocketBridgeSysfsInpocket) + ); + mPrintWriter = new FastPrintWriter(mFileOutputStream, true, 128); + } + catch(FileNotFoundException e) { + Slog.w(TAG, "Pocket bridge error occured", e); + setEnabled(false); + } + } + + @Override + public void handleMessage(android.os.Message msg) { + if (msg.what != MSG_POCKET_STATE_CHANGED) { + Slog.w(TAG, "Unknown message:" + msg.what); + return; + } + + if (mPrintWriter != null) { + mPrintWriter.println(mIsDeviceInPocket ? 1 : 0); + } + } + + } + + private class PocketBridgeObserver extends ContentObserver { + + private boolean mRegistered; + + public PocketBridgeObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange) { + final boolean enabled = System.getIntForUser(mContext.getContentResolver(), + POCKET_JUDGE, 0 /* default */, UserHandle.USER_CURRENT) != 0; + setEnabled(enabled); + } + + public void register() { + if (!mRegistered) { + mContext.getContentResolver().registerContentObserver( + System.getUriFor(POCKET_JUDGE), true, this); + mRegistered = true; + } + } + + public void unregister() { + if (mRegistered) { + mContext.getContentResolver().unregisterContentObserver(this); + mRegistered = false; + } + } + + } + +} diff --git a/services/core/java/com/android/server/pocket/PocketService.java b/services/core/java/com/android/server/pocket/PocketService.java new file mode 100644 index 00000000000..9be31830e1b --- /dev/null +++ b/services/core/java/com/android/server/pocket/PocketService.java @@ -0,0 +1,751 @@ +/** + * Copyright (C) 2016 The ParanoidAndroid Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.pocket; + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; +import android.database.ContentObserver; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.Binder; +import android.os.DeadObjectException; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.Process; +import android.os.RemoteException; +import android.os.SystemClock; +import android.os.UserHandle; +import android.pocket.IPocketService; +import android.pocket.IPocketCallback; +import android.pocket.PocketConstants; +import android.pocket.PocketManager; +import android.provider.Settings.System; +import android.util.Log; +import android.util.Slog; + +import com.android.server.SystemService; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; + +import static android.provider.Settings.System.POCKET_JUDGE; + +/** + * A service to manage multiple clients that want to listen for pocket state. + * The service is responsible for maintaining a list of clients and dispatching all + * pocket -related information. + * + * @author Carlo Savignano + * @hide + */ +public class PocketService extends SystemService implements IBinder.DeathRecipient { + + private static final String TAG = PocketService.class.getSimpleName(); + private static final boolean DEBUG = PocketConstants.DEBUG; + + /** + * The rate proximity sensor events are delivered at. + */ + private static final int PROXIMITY_SENSOR_DELAY = 400000; + + /** + * Wheater we don't have yet a valid proximity sensor event or pocket service not running. + */ + private static final int PROXIMITY_UNKNOWN = 0; + + /** + * Proximity sensor has been registered, onSensorChanged() has been called and we have a + * valid event value which determined proximity sensor is covered. + */ + private static final int PROXIMITY_POSITIVE = 1; + + /** + * Proximity sensor has been registered, onSensorChanged() has been called and we have a + * valid event value which determined proximity sensor is not covered. + */ + private static final int PROXIMITY_NEGATIVE = 2; + + /** + * The rate light sensor events are delivered at. + */ + private static final int LIGHT_SENSOR_DELAY = 400000; + + /** + * Wheater we don't have yet a valid light sensor event or pocket service not running. + */ + private static final int LIGHT_UNKNOWN = 0; + + /** + * Light sensor has been registered, onSensorChanged() has been called and we have a + * valid event value which determined available light is in pocket range. + */ + private static final int LIGHT_POCKET = 1; + + /** + * Light sensor has been registered, onSensorChanged() has been called and we have a + * valid event value which determined available light is outside pocket range. + */ + private static final int LIGHT_AMBIENT = 2; + + /** + * Light sensor maximum value registered in pocket with up to semi-transparent fabric. + */ + private static final float POCKET_LIGHT_MAX_THRESHOLD = 3.0f; + + private final ArrayList mCallbacks= new ArrayList<>(); + + private Context mContext; + private boolean mEnabled; + private boolean mSystemReady; + private boolean mSystemBooted; + private boolean mInteractive; + private boolean mPending; + private PocketHandler mHandler; + private PocketObserver mObserver; + private SensorManager mSensorManager; + + // proximity + private int mProximityState = PROXIMITY_UNKNOWN; + private int mLastProximityState = PROXIMITY_UNKNOWN; + private float mProximityMaxRange; + private boolean mProximityRegistered; + private Sensor mProximitySensor; + + // light + private int mLightState = LIGHT_UNKNOWN; + private int mLastLightState = LIGHT_UNKNOWN; + private float mLightMaxRange; + private boolean mLightRegistered; + private Sensor mLightSensor; + + // Custom methods + private boolean mPocketLockVisible; + + public PocketService(Context context) { + super(context); + mContext = context; + HandlerThread handlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND); + handlerThread.start(); + mHandler = new PocketHandler(handlerThread.getLooper()); + mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); + mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); + if (mProximitySensor != null) { + mProximityMaxRange = mProximitySensor.getMaximumRange(); + } + mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); + if (mLightSensor != null) { + mLightMaxRange = mLightSensor.getMaximumRange(); + } + mObserver = new PocketObserver(mHandler); + mObserver.onChange(true); + mObserver.register(); + } + + private class PocketObserver extends ContentObserver { + + private boolean mRegistered; + + public PocketObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange) { + final boolean enabled = System.getIntForUser(mContext.getContentResolver(), + POCKET_JUDGE, 0 /* default */, UserHandle.USER_CURRENT) != 0; + setEnabled(enabled); + } + + public void register() { + if (!mRegistered) { + mContext.getContentResolver().registerContentObserver( + System.getUriFor(POCKET_JUDGE), true, this); + mRegistered = true; + } + } + + public void unregister() { + if (mRegistered) { + mContext.getContentResolver().unregisterContentObserver(this); + mRegistered = false; + } + } + + } + + private class PocketHandler extends Handler { + + public static final int MSG_SYSTEM_READY = 0; + public static final int MSG_SYSTEM_BOOTED = 1; + public static final int MSG_DISPATCH_CALLBACKS = 2; + public static final int MSG_ADD_CALLBACK = 3; + public static final int MSG_REMOVE_CALLBACK = 4; + public static final int MSG_INTERACTIVE_CHANGED = 5; + public static final int MSG_SENSOR_EVENT_PROXIMITY = 6; + public static final int MSG_SENSOR_EVENT_LIGHT = 7; + public static final int MSG_UNREGISTER_TIMEOUT = 8; + public static final int MSG_SET_LISTEN_EXTERNAL = 9; + public static final int MSG_SET_POCKET_LOCK_VISIBLE = 10; + + public PocketHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(android.os.Message msg) { + switch (msg.what) { + case MSG_SYSTEM_READY: + handleSystemReady(); + break; + case MSG_SYSTEM_BOOTED: + handleSystemBooted(); + break; + case MSG_DISPATCH_CALLBACKS: + handleDispatchCallbacks(); + break; + case MSG_ADD_CALLBACK: + handleAddCallback((IPocketCallback) msg.obj); + break; + case MSG_REMOVE_CALLBACK: + handleRemoveCallback((IPocketCallback) msg.obj); + break; + case MSG_INTERACTIVE_CHANGED: + handleInteractiveChanged(msg.arg1 != 0); + break; + case MSG_SENSOR_EVENT_PROXIMITY: + handleProximitySensorEvent((SensorEvent) msg.obj); + break; + case MSG_SENSOR_EVENT_LIGHT: + handleLightSensorEvent((SensorEvent) msg.obj); + break; + case MSG_UNREGISTER_TIMEOUT: + handleUnregisterTimeout(); + break; + case MSG_SET_LISTEN_EXTERNAL: + handleSetListeningExternal(msg.arg1 != 0); + break; + case MSG_SET_POCKET_LOCK_VISIBLE: + handleSetPocketLockVisible(msg.arg1 != 0); + break; + default: + Slog.w(TAG, "Unknown message:" + msg.what); + } + } + } + + @Override + public void onBootPhase(int phase) { + switch(phase) { + case PHASE_SYSTEM_SERVICES_READY: + mHandler.sendEmptyMessage(PocketHandler.MSG_SYSTEM_READY); + break; + case PHASE_BOOT_COMPLETED: + mHandler.sendEmptyMessage(PocketHandler.MSG_SYSTEM_BOOTED); + break; + default: + Slog.w(TAG, "Un-handled boot phase:" + phase); + break; + } + } + + @Override + public void onStart() { + publishBinderService(Context.POCKET_SERVICE, new PocketServiceWrapper()); + } + + @Override + public void binderDied() { + synchronized (mCallbacks) { + mProximityState = PROXIMITY_UNKNOWN; + int callbacksSize = mCallbacks.size(); + for (int i = callbacksSize - 1; i >= 0; i--) { + if (mCallbacks.get(i) != null) { + try { + mCallbacks.get(i).onStateChanged(false, PocketManager.REASON_RESET); + } catch (DeadObjectException e) { + Slog.w(TAG, "Death object while invoking sendPocketState: ", e); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to invoke sendPocketState: ", e); + } + } + } + mCallbacks.clear(); + } + unregisterSensorListeners(); + mObserver.unregister(); + } + + private final class PocketServiceWrapper extends IPocketService.Stub { + + @Override // Binder call + public void addCallback(final IPocketCallback callback) { + final Message msg = new Message(); + msg.what = PocketHandler.MSG_ADD_CALLBACK; + msg.obj = callback; + mHandler.sendMessage(msg); + } + + @Override // Binder call + public void removeCallback(final IPocketCallback callback) { + final Message msg = new Message(); + msg.what = PocketHandler.MSG_REMOVE_CALLBACK; + msg.obj = callback; + mHandler.sendMessage(msg); + } + + @Override // Binder call + public void onInteractiveChanged(final boolean interactive) { + final Message msg = new Message(); + msg.what = PocketHandler.MSG_INTERACTIVE_CHANGED; + msg.arg1 = interactive ? 1 : 0; + mHandler.sendMessage(msg); + } + + @Override // Binder call + public void setListeningExternal(final boolean listen) { + final Message msg = new Message(); + msg.what = PocketHandler.MSG_SET_LISTEN_EXTERNAL; + msg.arg1 = listen ? 1 : 0; + mHandler.sendMessage(msg); + } + + @Override // Binder call + public boolean isDeviceInPocket() { + final long ident = Binder.clearCallingIdentity(); + try { + if (!mSystemReady || !mSystemBooted) { + return false; + } + return PocketService.this.isDeviceInPocket(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void setPocketLockVisible(final boolean visible) { + final Message msg = new Message(); + msg.what = PocketHandler.MSG_SET_POCKET_LOCK_VISIBLE; + msg.arg1 = visible ? 1 : 0; + mHandler.sendMessage(msg); + } + + @Override // Binder call + public boolean isPocketLockVisible() { + final long ident = Binder.clearCallingIdentity(); + try { + if (!mSystemReady || !mSystemBooted) { + return false; + } + return PocketService.this.isPocketLockVisible(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump Pocket from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + final long ident = Binder.clearCallingIdentity(); + try { + dumpInternal(pw); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + } + + private final SensorEventListener mProximityListener = new SensorEventListener() { + @Override + public void onSensorChanged(SensorEvent sensorEvent) { + final Message msg = new Message(); + msg.what = PocketHandler.MSG_SENSOR_EVENT_PROXIMITY; + msg.obj = sensorEvent; + mHandler.sendMessage(msg); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int i) { } + }; + + private final SensorEventListener mLightListener = new SensorEventListener() { + @Override + public void onSensorChanged(SensorEvent sensorEvent) { + final Message msg = new Message(); + msg.what = PocketHandler.MSG_SENSOR_EVENT_LIGHT; + msg.obj = sensorEvent; + mHandler.sendMessage(msg); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int i) { } + }; + + private boolean isDeviceInPocket() { + if (mLightState != LIGHT_UNKNOWN) { + return mProximityState == PROXIMITY_POSITIVE + && mLightState == LIGHT_POCKET; + } + return mProximityState == PROXIMITY_POSITIVE; + } + + private void setEnabled(boolean enabled) { + if (enabled != mEnabled) { + mEnabled = enabled; + mHandler.removeCallbacksAndMessages(null); + update(); + } + } + + private void update() { + if (!mEnabled || mInteractive) { + if (mEnabled && isDeviceInPocket()) { + // if device is judged to be in pocket while switching + // to interactive state, we need to keep monitoring. + return; + } + unregisterSensorListeners(); + } else { + mHandler.removeMessages(PocketHandler.MSG_UNREGISTER_TIMEOUT); + registerSensorListeners(); + } + } + + private void registerSensorListeners() { + startListeningForProximity(); + startListeningForLight(); + } + + private void unregisterSensorListeners() { + stopListeningForProximity(); + stopListeningForLight(); + } + + private void startListeningForProximity() { + if (DEBUG) { + Log.d(TAG, "startListeningForProximity()"); + } + + if (!PocketConstants.ENABLE_PROXIMITY_JUDGE) { + return; + } + + if (mProximitySensor == null) { + Log.d(TAG, "Cannot detect proximity sensor, sensor is NULL"); + return; + } + + if (!mProximityRegistered) { + mSensorManager.registerListener(mProximityListener, mProximitySensor, + PROXIMITY_SENSOR_DELAY, mHandler); + mProximityRegistered = true; + } + } + + private void stopListeningForProximity() { + if (DEBUG) { + Log.d(TAG, "startListeningForProximity()"); + } + + if (mProximityRegistered) { + mLastProximityState = mProximityState = PROXIMITY_UNKNOWN; + mSensorManager.unregisterListener(mProximityListener); + mProximityRegistered = false; + } + } + + private void startListeningForLight() { + if (DEBUG) { + Log.d(TAG, "startListeningForLight()"); + } + + if (!PocketConstants.ENABLE_LIGHT_JUDGE) { + return; + } + + if (mLightSensor == null) { + Log.d(TAG, "Cannot detect light sensor, sensor is NULL"); + return; + } + + if (!mLightRegistered) { + mSensorManager.registerListener(mLightListener, mLightSensor, + LIGHT_SENSOR_DELAY, mHandler); + mLightRegistered = true; + } + } + + private void stopListeningForLight() { + if (DEBUG) { + Log.d(TAG, "stopListeningForLight()"); + } + + if (mLightRegistered) { + mLightState = mLastLightState = LIGHT_UNKNOWN; + mSensorManager.unregisterListener(mLightListener); + mLightRegistered = false; + } + } + + private void handleSystemReady() { + if (DEBUG) { + Log.d(TAG, "onBootPhase(): PHASE_SYSTEM_SERVICES_READY"); + } + mSystemReady = true; + if (mPending) { + final Message msg = new Message(); + msg.what = PocketHandler.MSG_INTERACTIVE_CHANGED; + msg.arg1 = mInteractive ? 1 : 0; + mHandler.sendMessage(msg); + mPending = false; + } + } + + private void handleSystemBooted() { + if (DEBUG) { + Log.d(TAG, "onBootPhase(): PHASE_BOOT_COMPLETED"); + } + mSystemBooted = true; + if (mPending) { + final Message msg = new Message(); + msg.what = PocketHandler.MSG_INTERACTIVE_CHANGED; + msg.arg1 = mInteractive ? 1 : 0; + mHandler.sendMessage(msg); + mPending = false; + } + } + + private void handleDispatchCallbacks() { + synchronized (mCallbacks) { + final int N = mCallbacks.size(); + boolean cleanup = false; + for (int i = 0; i < N; i++) { + final IPocketCallback callback = mCallbacks.get(i); + try { + if (callback != null) { + callback.onStateChanged(isDeviceInPocket(), PocketManager.REASON_SENSOR); + } else { + cleanup = true; + } + } catch (RemoteException e) { + cleanup = true; + } + } + if (cleanup) { + cleanUpCallbacksLocked(null); + } + } + } + + private void cleanUpCallbacksLocked(IPocketCallback callback) { + synchronized (mCallbacks) { + for (int i = mCallbacks.size() - 1; i >= 0; i--) { + IPocketCallback found = mCallbacks.get(i); + if (found == null || found == callback) { + mCallbacks.remove(i); + } + } + } + } + + private void handleSetPocketLockVisible(boolean visible) { + mPocketLockVisible = visible; + } + + private boolean isPocketLockVisible() { + return mPocketLockVisible; + } + + private void handleSetListeningExternal(boolean listen) { + if (listen) { + // should prevent external processes to register while interactive, + // while they are allowed to stop listening in any case as for example + // coming pocket lock will need to. + if (!mInteractive) { + registerSensorListeners(); + } + } else { + mHandler.removeCallbacksAndMessages(null); + unregisterSensorListeners(); + } + dispatchCallbacks(); + } + + private void handleAddCallback(IPocketCallback callback) { + synchronized (mCallbacks) { + if (!mCallbacks.contains(callback)) { + mCallbacks.add(callback); + } + } + } + + private void handleRemoveCallback(IPocketCallback callback) { + synchronized (mCallbacks) { + if (mCallbacks.contains(callback)) { + mCallbacks.remove(callback); + } + } + } + + private void handleInteractiveChanged(boolean interactive) { + // always update interactive state. + mInteractive = interactive; + + if (mPending) { + // working on it, waiting for proper system conditions. + return; + } else if (!mPending && (!mSystemBooted || !mSystemReady)) { + // we ain't ready, postpone till system is both booted AND ready. + mPending = true; + return; + } + + update(); + } + + private void handleLightSensorEvent(SensorEvent sensorEvent) { + final boolean isDeviceInPocket = isDeviceInPocket(); + + mLastLightState = mLightState; + + if (DEBUG) { + final String sensorEventToString = sensorEvent != null ? sensorEvent.toString() : "NULL"; + Log.d(TAG, "LIGHT_SENSOR: onSensorChanged(), sensorEvent =" + sensorEventToString); + } + + try { + if (sensorEvent == null) { + if (DEBUG) Log.d(TAG, "Event is null!"); + mLightState = LIGHT_UNKNOWN; + } else if (sensorEvent.values == null || sensorEvent.values.length == 0) { + if (DEBUG) Log.d(TAG, "Event has no values! event.values null ? " + (sensorEvent.values == null)); + mLightState = LIGHT_UNKNOWN; + } else { + final float value = sensorEvent.values[0]; + final boolean isPoor = value >= 0 + && value <= POCKET_LIGHT_MAX_THRESHOLD; + if (DEBUG) { + final long time = SystemClock.uptimeMillis(); + Log.d(TAG, "Event: time= " + time + ", value=" + value + + ", maxRange=" + mLightMaxRange + ", isPoor=" + isPoor); + } + mLightState = isPoor ? LIGHT_POCKET : LIGHT_AMBIENT; + } + } catch (NullPointerException e) { + Log.e(TAG, "Event: something went wrong, exception caught, e = " + e); + mLightState = LIGHT_UNKNOWN; + } finally { + if (isDeviceInPocket != isDeviceInPocket()) { + dispatchCallbacks(); + } + } + } + + private void handleProximitySensorEvent(SensorEvent sensorEvent) { + final boolean isDeviceInPocket = isDeviceInPocket(); + + mLastProximityState = mProximityState; + + if (DEBUG) { + final String sensorEventToString = sensorEvent != null ? sensorEvent.toString() : "NULL"; + Log.d(TAG, "PROXIMITY_SENSOR: onSensorChanged(), sensorEvent =" + sensorEventToString); + } + + try { + if (sensorEvent == null) { + if (DEBUG) Log.d(TAG, "Event is null!"); + mProximityState = PROXIMITY_UNKNOWN; + } else if (sensorEvent.values == null || sensorEvent.values.length == 0) { + if (DEBUG) Log.d(TAG, "Event has no values! event.values null ? " + (sensorEvent.values == null)); + mProximityState = PROXIMITY_UNKNOWN; + } else { + final float value = sensorEvent.values[0]; + final boolean isPositive = sensorEvent.values[0] < mProximityMaxRange; + if (DEBUG) { + final long time = SystemClock.uptimeMillis(); + Log.d(TAG, "Event: time=" + time + ", value=" + value + + ", maxRange=" + mProximityMaxRange + ", isPositive=" + isPositive); + } + mProximityState = isPositive ? PROXIMITY_POSITIVE : PROXIMITY_NEGATIVE; + } + } catch (NullPointerException e) { + Log.e(TAG, "Event: something went wrong, exception caught, e = " + e); + mProximityState = PROXIMITY_UNKNOWN; + } finally { + if (isDeviceInPocket != isDeviceInPocket()) { + dispatchCallbacks(); + } + } + } + + private void handleUnregisterTimeout() { + mHandler.removeCallbacksAndMessages(null); + unregisterSensorListeners(); + } + + private void dispatchCallbacks() { + final boolean isDeviceInPocket = isDeviceInPocket(); + if (mInteractive) { + if (!isDeviceInPocket) { + mHandler.sendEmptyMessageDelayed(PocketHandler.MSG_UNREGISTER_TIMEOUT, 5000 /* ms */); + } else { + mHandler.removeMessages(PocketHandler.MSG_UNREGISTER_TIMEOUT); + } + } + mHandler.removeMessages(PocketHandler.MSG_DISPATCH_CALLBACKS); + mHandler.sendEmptyMessage(PocketHandler.MSG_DISPATCH_CALLBACKS); + } + + private void dumpInternal(PrintWriter pw) { + JSONObject dump = new JSONObject(); + try { + dump.put("service", "POCKET"); + dump.put("enabled", mEnabled); + dump.put("isDeviceInPocket", isDeviceInPocket()); + dump.put("interactive", mInteractive); + dump.put("proximityState", mProximityState); + dump.put("lastProximityState", mLastProximityState); + dump.put("proximityRegistered", mProximityRegistered); + dump.put("proximityMaxRange", mProximityMaxRange); + dump.put("lightState", mLightState); + dump.put("lastLightState", mLastLightState); + dump.put("lightRegistered", mLightRegistered); + dump.put("lightMaxRange", mLightMaxRange); + } catch (JSONException e) { + Slog.e(TAG, "dump formatting failure", e); + } finally { + pw.println(dump); + } + } +} diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 35ca32dc70c..fa9a56b190a 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -158,6 +158,8 @@ import android.os.VibrationEffect; import android.os.Vibrator; import android.provider.DeviceConfig; +import android.pocket.IPocketCallback; +import android.pocket.PocketManager; import android.provider.MediaStore; import android.provider.Settings; import android.service.dreams.DreamManagerInternal; @@ -219,6 +221,7 @@ import com.android.server.policy.keyguard.KeyguardServiceDelegate; import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener; import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback; +import com.android.server.policy.pocket.PocketLock; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.vr.VrManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; @@ -282,6 +285,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final int LONG_PRESS_POWER_GO_TO_VOICE_ASSIST = 4; static final int LONG_PRESS_POWER_ASSISTANT = 5; // Settings.Secure.ASSISTANT static final int LONG_PRESS_POWER_TORCH = 10; + static final int LONG_PRESS_POWER_HIDE_POCKET_LOCK = 7; // must match: config_veryLongPresOnPowerBehavior in config.xml static final int VERY_LONG_PRESS_POWER_NOTHING = 0; @@ -691,6 +695,30 @@ public void onTorchModeUnavailable(String cameraId) { }; private boolean mLockNowPending = false; + private PocketManager mPocketManager; + private PocketLock mPocketLock; + private boolean mPocketLockShowing; + private boolean mIsDeviceInPocket; + private final IPocketCallback mPocketCallback = new IPocketCallback.Stub() { + + @Override + public void onStateChanged(boolean isDeviceInPocket, int reason) { + boolean wasDeviceInPocket = mIsDeviceInPocket; + if (reason == PocketManager.REASON_SENSOR) { + mIsDeviceInPocket = isDeviceInPocket; + } else { + mIsDeviceInPocket = false; + } + if (wasDeviceInPocket != mIsDeviceInPocket) { + handleDevicePocketStateChanged(); + //if (mKeyHandler != null) { + //mKeyHandler.setIsInPocket(mIsDeviceInPocket); + //} + } + } + + }; + private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3; private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4; private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5; @@ -1083,6 +1111,9 @@ private void interceptPowerKeyDown(KeyEvent event, boolean interactive) { mPowerKeyWakeLock.acquire(); } + // Still allow muting call with power button press. + boolean blockInputs = mIsDeviceInPocket && (!interactive || mPocketLockShowing); + // Cancel multi-press detection timeout. if (mPowerKeyPressCounter != 0) { mHandler.removeMessages(MSG_POWER_DELAYED_PRESS); @@ -1090,15 +1121,20 @@ private void interceptPowerKeyDown(KeyEvent event, boolean interactive) { mWindowManagerFuncs.onPowerKeyDown(interactive); - // Latch power key state to detect screenshot chord. - if (interactive && !mScreenshotChordPowerKeyTriggered - && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { - mScreenshotChordPowerKeyTriggered = true; - mScreenshotChordPowerKeyTime = event.getDownTime(); - interceptScreenshotChord(); - interceptRingerToggleChord(); + if (!blockInputs) { + // Latch power key state to detect screenshot chord. + if (interactive && !mScreenshotChordPowerKeyTriggered + && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { + mScreenshotChordPowerKeyTriggered = true; + mScreenshotChordPowerKeyTime = event.getDownTime(); + interceptScreenshotChord(); + interceptRingerToggleChord(); + } } + // Abort possibly stuck animations. + mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe); + // Stop ringing or end call if configured to do so when power is pressed. TelecomManager telecomManager = getTelecommService(); boolean hungUp = false; @@ -1107,7 +1143,7 @@ private void interceptPowerKeyDown(KeyEvent event, boolean interactive) { // Pressing Power while there's a ringing incoming // call should silence the ringer. telecomManager.silenceRinger(); - } else if ((mIncallPowerBehavior + } else if (!blockInputs && (mIncallPowerBehavior & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 && telecomManager.isInCall() && interactive) { // Otherwise, if "Power button ends call" is enabled, @@ -1118,14 +1154,16 @@ private void interceptPowerKeyDown(KeyEvent event, boolean interactive) { final boolean handledByPowerManager = mPowerManagerInternal.interceptPowerKeyDown(event); - GestureLauncherService gestureService = LocalServices.getService( - GestureLauncherService.class); boolean gesturedServiceIntercepted = false; - if (gestureService != null) { - gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive, - mTmpBoolean); - if (mTmpBoolean.value && mRequestedOrGoingToSleep) { - mCameraGestureTriggeredDuringGoingToSleep = true; + if (!blockInputs) { + GestureLauncherService gestureService = LocalServices.getService( + GestureLauncherService.class); + if (gestureService != null) { + gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive, + mTmpBoolean); + if (mTmpBoolean.value && mRequestedOrGoingToSleep) { + mCameraGestureTriggeredDuringGoingToSleep = true; + } } } @@ -1483,6 +1521,13 @@ private void powerLongPress() { msg.setAsynchronous(true); msg.sendToTarget(); break; + case LONG_PRESS_POWER_HIDE_POCKET_LOCK: + mPowerKeyHandled = true; + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, + "Power - Long Press - Hide Pocket Lock"); + hidePocketLock(true); + mPocketManager.setListeningExternal(false); + break; } } @@ -1539,6 +1584,9 @@ private int getResolvedLongPressOnPowerBehavior() { if ((mTorchActionMode == 1) && (!isScreenOn() || mTorchEnabled)) { return LONG_PRESS_POWER_TORCH; } + if (mPocketLockShowing) { + return LONG_PRESS_POWER_HIDE_POCKET_LOCK; + } return mLongPressOnPowerBehavior; } @@ -1663,7 +1711,9 @@ public void setScreenshotSource(int screenshotSource) { @Override public void run() { - mDefaultDisplayPolicy.takeScreenshot(mScreenshotType, mScreenshotSource); + if (!mPocketLockShowing){ + mDefaultDisplayPolicy.takeScreenshot(mScreenshotType, mScreenshotSource); + } } } @@ -2099,7 +2149,9 @@ public void init(Context context, IWindowManager windowManager, mOPGestures = new OPGesturesListener(context, new OPGesturesListener.Callbacks() { @Override public void onSwipeThreeFinger() { - mHandler.post(mScreenshotRunnable); + if (!mPocketLockShowing) { + mHandler.post(mScreenshotRunnable); + } } }); mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler); @@ -4231,6 +4283,23 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { return 0; } + // Pre-basic policy based on interactive and pocket lock state. + if (mIsDeviceInPocket && (!interactive || mPocketLockShowing)) { + if (keyCode != KeyEvent.KEYCODE_POWER && + keyCode != KeyEvent.KEYCODE_VOLUME_UP && + keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && + keyCode != KeyEvent.KEYCODE_MEDIA_PLAY && + keyCode != KeyEvent.KEYCODE_MEDIA_PAUSE && + keyCode != KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE && + keyCode != KeyEvent.KEYCODE_HEADSETHOOK && + keyCode != KeyEvent.KEYCODE_MEDIA_STOP && + keyCode != KeyEvent.KEYCODE_MEDIA_NEXT && + keyCode != KeyEvent.KEYCODE_MEDIA_PREVIOUS && + keyCode != KeyEvent.KEYCODE_VOLUME_MUTE) { + return 0; + } + } + // Basic policy based on interactive state. final boolean isVolumeRockerWake = !isScreenOn() && mVolumeRockerWake @@ -5160,6 +5229,9 @@ public void startedGoingToSleep(int why) { if (mKeyguardDelegate != null) { mKeyguardDelegate.onStartedGoingToSleep(why); } + if (mPocketManager != null) { + mPocketManager.onInteractiveChanged(false); + } } // Called on the PowerManager's Notifier thread. @@ -5218,6 +5290,10 @@ public void startedWakingUp(@OnReason int why) { if (mKeyguardDelegate != null) { mKeyguardDelegate.onStartedWakingUp(); } + + if (mPocketManager != null) { + mPocketManager.onInteractiveChanged(true); + } } // Called on the PowerManager's Notifier thread. @@ -5407,6 +5483,72 @@ private void finishScreenTurningOn() { } } + /** + * Perform operations if needed on pocket mode state changed. + * @see com.android.server.pocket.PocketService + * @see PocketLock + * @see this.mPocketCallback; + * @author Carlo Savignano + */ + private void handleDevicePocketStateChanged() { + final boolean interactive = mPowerManager.isInteractive(); + if (mIsDeviceInPocket) { + showPocketLock(interactive); + } else { + hidePocketLock(interactive); + } + } + + /** + * Check if we can show pocket lock once requested. + * @see com.android.server.pocket.PocketService + * @see PocketLock + * @see this.mPocketCallback; + * @author Carlo Savignano + */ + private void showPocketLock(boolean animate) { + if (!mSystemReady || !mSystemBooted || !mKeyguardDrawnOnce + || mPocketLock == null || mPocketLockShowing) { + return; + } + + if (mPowerManager.isInteractive() && !isKeyguardShowingAndNotOccluded()){ + return; + } + + if (DEBUG_INPUT) { + Log.d(TAG, "showPocketLock, animate=" + animate); + } + + mPocketLock.show(animate); + mPocketLockShowing = true; + + mPocketManager.setPocketLockVisible(true); + } + + /** + * Check if we can hide pocket lock once requested. + * @see com.android.server.pocket.PocketService + * @see PocketLock + * @see this.mPocketCallback; + * @author Carlo Savignano + */ + private void hidePocketLock(boolean animate) { + if (!mSystemReady || !mSystemBooted || !mKeyguardDrawnOnce + || mPocketLock == null || !mPocketLockShowing) { + return; + } + + if (DEBUG_INPUT) { + Log.d(TAG, "hidePocketLock, animate=" + animate); + } + + mPocketLock.hide(animate); + mPocketLockShowing = false; + + mPocketManager.setPocketLockVisible(false); + } + private void handleHideBootMessage() { synchronized (mLock) { if (!mKeyguardDrawnOnce) { @@ -5567,6 +5709,10 @@ public void systemReady() { // So it is better not to bind keyguard here. mKeyguardDelegate.onSystemReady(); + mPocketManager = (PocketManager) mContext.getSystemService(Context.POCKET_SERVICE); + mPocketManager.addCallback(mPocketCallback); + mPocketLock = new PocketLock(mContext); + mVrManagerInternal = LocalServices.getService(VrManagerInternal.class); if (mVrManagerInternal != null) { mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener); diff --git a/services/core/java/com/android/server/policy/pocket/PocketLock.java b/services/core/java/com/android/server/policy/pocket/PocketLock.java new file mode 100644 index 00000000000..09e77c195d3 --- /dev/null +++ b/services/core/java/com/android/server/policy/pocket/PocketLock.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2016 The ParanoidAndroid Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.policy.pocket; + +import android.animation.Animator; +import android.content.Context; +import android.graphics.PixelFormat; +import android.os.Handler; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; + +/** + * This class provides a fullscreen overlays view, displaying itself + * even on top of lock screen. While this view is displaying touch + * inputs are not passed to the the views below. + * @see android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; + * @author Carlo Savignano + */ +public class PocketLock { + + private final Context mContext; + private WindowManager mWindowManager; + private WindowManager.LayoutParams mLayoutParams; + private Handler mHandler; + private View mView; + private View mHintContainer; + + private boolean mAttached; + private boolean mAnimating; + + /** + * Creates pocket lock objects, inflate view and set layout parameters. + * @param context + */ + public PocketLock(Context context) { + mContext = context; + mHandler = new Handler(); + mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); + mLayoutParams = getLayoutParams(); + mView = LayoutInflater.from(mContext).inflate( + com.android.internal.R.layout.pocket_lock_view_layout, null); + } + + public void show(final boolean animate) { + final Runnable r = new Runnable() { + @Override + public void run() { + if (mAttached) { + return; + } + + if (mAnimating) { + mView.animate().cancel(); + } + + if (animate) { + mView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + mView.animate().alpha(1.0f).setListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) { + mAnimating = true; + } + + @Override + public void onAnimationEnd(Animator animator) { + mView.setLayerType(View.LAYER_TYPE_NONE, null); + mAnimating = false; + } + + @Override + public void onAnimationCancel(Animator animator) { + } + + @Override + public void onAnimationRepeat(Animator animator) { + } + }).withStartAction(new Runnable() { + @Override + public void run() { + mView.setAlpha(0.0f); + mView.setVisibility(View.VISIBLE); + addView(); + } + }).start(); + } else { + mView.setVisibility(View.VISIBLE); + mView.setAlpha(1.0f); + addView(); + } + } + }; + + mHandler.post(r); + } + + public void hide(final boolean animate) { + final Runnable r = new Runnable() { + @Override + public void run() { + if (!mAttached) { + return; + } + + if (mAnimating) { + mView.animate().cancel(); + } + + if (animate) { + mView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + mView.animate().alpha(0.0f).setListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) { + mAnimating = true; + } + + @Override + public void onAnimationEnd(Animator animator) { + mView.setVisibility(View.GONE); + mView.setLayerType(View.LAYER_TYPE_NONE, null); + mAnimating = false; + removeView(); + } + + @Override + public void onAnimationCancel(Animator animator) { + } + + @Override + public void onAnimationRepeat(Animator animator) { + } + }).start(); + } else { + mView.setVisibility(View.GONE); + mView.setAlpha(0.0f); + removeView(); + } + } + }; + + mHandler.post(r); + } + + private void addView() { + if (mWindowManager != null && !mAttached) { + mWindowManager.addView(mView, mLayoutParams); + mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_POCKET_LOCK); + mAttached = true; + } + } + + private void removeView() { + if (mWindowManager != null && mAttached) { + mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + mWindowManager.removeView(mView); + mAnimating = false; + mAttached = false; + } + } + + private WindowManager.LayoutParams getLayoutParams() { + mLayoutParams = new WindowManager.LayoutParams(); + mLayoutParams.format = PixelFormat.TRANSLUCENT; + mLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT; + mLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; + mLayoutParams.gravity = Gravity.CENTER; + mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; + mLayoutParams.layoutInDisplayCutoutMode = + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + mLayoutParams.flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH + | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED + | WindowManager.LayoutParams.FLAG_FULLSCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; + return mLayoutParams; + } + +} diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index bef45439fcd..60fb3a5f028 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -3917,6 +3917,7 @@ private Pair updateSystemBarsLw(WindowState win, int oldVi final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; final boolean navAllowedHidden = immersive || immersiveSticky; + final boolean isPocketLock = (vis & View.SYSTEM_UI_FLAG_POCKET_LOCK) != 0; if (hideNavBarSysui && !navAllowedHidden && mService.mPolicy.getWindowLayerLw(win) @@ -3935,7 +3936,7 @@ private Pair updateSystemBarsLw(WindowState win, int oldVi if (oldImmersiveMode != newImmersiveMode) { mLastImmersiveMode = newImmersiveMode; final String pkg = win.getOwningPackage(); - mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode, + mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, isPocketLock ? false : newImmersiveMode, mService.mPolicy.isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility())); } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 3d5230bff8f..9448dbfbbb8 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -136,6 +136,8 @@ import com.android.server.os.DeviceIdentifiersPolicyService; import com.android.server.os.SchedulingPolicyService; import com.android.server.people.PeopleService; +import com.android.server.pocket.PocketService; +import com.android.server.pocket.PocketBridgeService; import com.android.server.pm.BackgroundDexOptService; import com.android.server.pm.CrossProfileAppsService; import com.android.server.pm.DataLoaderManagerService; @@ -2047,6 +2049,18 @@ private void startOtherServices(@NonNull TimingsTraceAndSlog t) { mSystemServiceManager.startService(LineageHardwareService.class); t.traceEnd(); } + + // Pocket + t.traceBegin("StartPocketService"); + mSystemServiceManager.startService(PocketService.class); + t.traceEnd(); + + if (!context.getResources().getString( + com.android.internal.R.string.config_pocketBridgeSysfsInpocket).isEmpty()) { + t.traceBegin("StartPocketBridgeService"); + mSystemServiceManager.startService(PocketBridgeService.class); + t.traceEnd(); + } } if (!isWatch) { From 10ee40d0a103296ce33307955edf7c8c909f2ec5 Mon Sep 17 00:00:00 2001 From: jhenrique09 Date: Sat, 12 Sep 2020 13:35:49 -0300 Subject: [PATCH 02/51] Pocket lock: Improve on fod devices Change-Id: I144b0eb18bb8686e8ebd391532db3d80925a49e7 --- .../keyguard/KeyguardUpdateMonitor.java | 11 +++++- .../systemui/biometrics/FODCircleView.java | 39 ++++++++++++++++++- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 14029eafc52..af8438e6211 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -128,6 +128,7 @@ import javax.inject.Singleton; import com.android.internal.util.custom.faceunlock.FaceUnlockUtils; +import com.android.internal.util.custom.fod.FodUtils; import com.android.internal.util.custom.fod.FodUtils; @@ -333,6 +334,8 @@ public void onChanged(Integer ringer) { } }; + private boolean mHasFod; + private PocketManager mPocketManager; private boolean mIsDeviceInPocket; private final IPocketCallback mPocketCallback = new IPocketCallback.Stub() { @@ -708,6 +711,9 @@ private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiom private void handleFingerprintHelp(int msgId, String helpString) { Assert.isMainThread(); + if (mIsDeviceInPocket && mHasFod){ + return; + } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -1876,6 +1882,7 @@ public void handleMessage(Message msg) { } } } + mHasFod = FodUtils.hasFodSupport(mContext); } private final UserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() { @@ -2007,14 +2014,14 @@ private boolean shouldListenForFingerprint() { (mKeyguardOccluded && mIsDreaming)) && mDeviceInteractive && !mGoingToSleep && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser()) && (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser - && allowedOnBouncer && !mIsDeviceInPocket; + && allowedOnBouncer && (mHasFod || !mIsDeviceInPocket); } else { return (mKeyguardIsVisible || !mDeviceInteractive || (mBouncer && !mKeyguardGoingAway) || mGoingToSleep || shouldListenForFingerprintAssistant() || (mKeyguardOccluded && mIsDreaming)) && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser()) && (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser - && allowedOnBouncer && !mIsDeviceInPocket; + && allowedOnBouncer && (mHasFod || !mIsDeviceInPocket); } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FODCircleView.java b/packages/SystemUI/src/com/android/systemui/biometrics/FODCircleView.java index 7176ea1aa63..3b73f399bf1 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/FODCircleView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/FODCircleView.java @@ -45,6 +45,8 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; +import android.pocket.IPocketCallback; +import android.pocket.PocketManager; import android.provider.Settings; import android.net.Uri; import android.view.Display; @@ -277,6 +279,7 @@ public void onKeyguardVisibilityChanged(boolean showing) { if (mFODAnimation != null) { mFODAnimation.setAnimationKeyguard(mIsKeyguard); } + handlePocketManagerCallback(showing); } @Override @@ -352,6 +355,20 @@ public void onBiometricHelp(int msgId, String helpString, } }; + private void handlePocketManagerCallback(boolean keyguardShowing){ + if (!keyguardShowing){ + if (mPocketCallbackAdded){ + mPocketCallbackAdded = false; + mPocketManager.removeCallback(mPocketCallback); + } + }else{ + if (!mPocketCallbackAdded){ + mPocketCallbackAdded = true; + mPocketManager.addCallback(mPocketCallback); + } + } + } + private class FodGestureSettingsObserver extends ContentObserver { FodGestureSettingsObserver(Context context, Handler handler) { super(handler); @@ -424,6 +441,23 @@ void update() { private CustomSettingsObserver mCustomSettingsObserver; private FodGestureSettingsObserver mFodGestureSettingsObserver; + private PocketManager mPocketManager; + private boolean mIsDeviceInPocket; + private boolean mPocketCallbackAdded = false; + private final IPocketCallback mPocketCallback = new IPocketCallback.Stub() { + + @Override + public void onStateChanged(boolean isDeviceInPocket, int reason) { + boolean wasDeviceInPocket = mIsDeviceInPocket; + if (reason == PocketManager.REASON_SENSOR) { + mIsDeviceInPocket = isDeviceInPocket; + } else { + mIsDeviceInPocket = false; + } + } + + }; + public FODCircleView(Context context) { super(context); mContext = context; @@ -520,6 +554,9 @@ protected void onDraw(Canvas canvas) { updateCutoutFlags(); Dependency.get(ConfigurationController.class).addCallback(this); + + // Pocket + mPocketManager = (PocketManager) context.getSystemService(Context.POCKET_SERVICE); } private int interpolate(int i, int i2, int i3, int i4, int i5) { @@ -681,7 +718,7 @@ public void dispatchHide() { } public void showCircle() { - if (mFading || mTouchedOutside) return; + if (mFading || mTouchedOutside || (mIsKeyguard && mIsDeviceInPocket)) return; mIsCircleShowing = true; setKeepScreenOn(true); From e0e6d21c1d53ed91dd31bbb941197dd19ef98fa0 Mon Sep 17 00:00:00 2001 From: DennySPb Date: Thu, 28 May 2020 20:59:47 +0300 Subject: [PATCH 03/51] PocketJudge: allow register vendor pocket sensor Some devices (ie OnePlus) have own pocket sensor. This change allow to use native pocket sensor instead of proximity and light. Sensor name must be specified in device tree overlay. In this case PocketService will try to use vendor sensor first. If sensor wasn't found, fallback sensors (proximity and light) will be in use. Example for OnePlus sensor: oneplus.sensor.pocket Change-Id: Ibe423478cfd9d49e0831e2df0af793178f62c0e0 --- core/res/res/values/custom_config.xml | 8 +- core/res/res/values/custom_symbols.xml | 4 +- .../android/server/pocket/PocketService.java | 134 ++++++++++++++++++ 3 files changed, 143 insertions(+), 3 deletions(-) diff --git a/core/res/res/values/custom_config.xml b/core/res/res/values/custom_config.xml index 4d132ee7912..5b20a03753e 100644 --- a/core/res/res/values/custom_config.xml +++ b/core/res/res/values/custom_config.xml @@ -215,6 +215,10 @@ to enable/disable DC dimming. --> - + to communicate pocket state to the pocket judge kernel driver. --> + + + + + diff --git a/core/res/res/values/custom_symbols.xml b/core/res/res/values/custom_symbols.xml index 5aa021d1dcd..4c620c96a6a 100644 --- a/core/res/res/values/custom_symbols.xml +++ b/core/res/res/values/custom_symbols.xml @@ -156,5 +156,7 @@ - + + + diff --git a/services/core/java/com/android/server/pocket/PocketService.java b/services/core/java/com/android/server/pocket/PocketService.java index 9be31830e1b..3585e11bd43 100644 --- a/services/core/java/com/android/server/pocket/PocketService.java +++ b/services/core/java/com/android/server/pocket/PocketService.java @@ -39,6 +39,7 @@ import android.pocket.PocketConstants; import android.pocket.PocketManager; import android.provider.Settings.System; +import android.text.TextUtils; import android.util.Log; import android.util.Slog; @@ -66,6 +67,17 @@ public class PocketService extends SystemService implements IBinder.DeathRecipie private static final String TAG = PocketService.class.getSimpleName(); private static final boolean DEBUG = PocketConstants.DEBUG; + /** + * Wheater we don't have yet a valid vendor sensor event or pocket service not running. + */ + private static final int VENDOR_SENSOR_UNKNOWN = 0; + + /** + * Vendor sensor has been registered, onSensorChanged() has been called and we have a + * valid event value from Vendor pocket sensor. + */ + private static final int VENDOR_SENSOR_IN_POCKET = 1; + /** * The rate proximity sensor events are delivered at. */ @@ -141,6 +153,13 @@ public class PocketService extends SystemService implements IBinder.DeathRecipie private boolean mLightRegistered; private Sensor mLightSensor; + // vendor sensor + private int mVendorSensorState = VENDOR_SENSOR_UNKNOWN; + private int mLastVendorSensorState = VENDOR_SENSOR_UNKNOWN; + private String mVendorPocketSensor; + private boolean mVendorSensorRegistered; + private Sensor mVendorSensor; + // Custom methods private boolean mPocketLockVisible; @@ -151,6 +170,8 @@ public PocketService(Context context) { handlerThread.start(); mHandler = new PocketHandler(handlerThread.getLooper()); mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); + mVendorPocketSensor = mContext.getResources().getString( + com.android.internal.R.string.config_pocketJudgeVendorSensorName); mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); if (mProximitySensor != null) { mProximityMaxRange = mProximitySensor.getMaximumRange(); @@ -159,6 +180,7 @@ public PocketService(Context context) { if (mLightSensor != null) { mLightMaxRange = mLightSensor.getMaximumRange(); } + mVendorSensor = getSensor(mSensorManager, mVendorPocketSensor); mObserver = new PocketObserver(mHandler); mObserver.onChange(true); mObserver.register(); @@ -209,6 +231,7 @@ private class PocketHandler extends Handler { public static final int MSG_UNREGISTER_TIMEOUT = 8; public static final int MSG_SET_LISTEN_EXTERNAL = 9; public static final int MSG_SET_POCKET_LOCK_VISIBLE = 10; + public static final int MSG_SENSOR_EVENT_VENDOR = 11; public PocketHandler(Looper looper) { super(looper); @@ -241,6 +264,9 @@ public void handleMessage(android.os.Message msg) { case MSG_SENSOR_EVENT_LIGHT: handleLightSensorEvent((SensorEvent) msg.obj); break; + case MSG_SENSOR_EVENT_VENDOR: + handleVendorSensorEvent((SensorEvent) msg.obj); + break; case MSG_UNREGISTER_TIMEOUT: handleUnregisterTimeout(); break; @@ -412,7 +438,24 @@ public void onSensorChanged(SensorEvent sensorEvent) { public void onAccuracyChanged(Sensor sensor, int i) { } }; + private final SensorEventListener mVendorSensorListener = new SensorEventListener() { + @Override + public void onSensorChanged(SensorEvent sensorEvent) { + final Message msg = new Message(); + msg.what = PocketHandler.MSG_SENSOR_EVENT_VENDOR; + msg.obj = sensorEvent; + mHandler.sendMessage(msg); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int i) { } + }; + private boolean isDeviceInPocket() { + if (mVendorSensorState != VENDOR_SENSOR_UNKNOWN) { + return mVendorSensorState == VENDOR_SENSOR_IN_POCKET; + } + if (mLightState != LIGHT_UNKNOWN) { return mProximityState == PROXIMITY_POSITIVE && mLightState == LIGHT_POCKET; @@ -443,16 +486,52 @@ private void update() { } private void registerSensorListeners() { + startListeningForVendorSensor(); startListeningForProximity(); startListeningForLight(); } private void unregisterSensorListeners() { + stopListeningForVendorSensor(); stopListeningForProximity(); stopListeningForLight(); } + private void startListeningForVendorSensor() { + if (DEBUG) { + Log.d(TAG, "startListeningForVendorSensor()"); + } + + if (mVendorSensor == null) { + Log.d(TAG, "Cannot detect Vendor pocket sensor, sensor is NULL"); + return; + } + + if (!mVendorSensorRegistered) { + mSensorManager.registerListener(mVendorSensorListener, mVendorSensor, + SensorManager.SENSOR_DELAY_NORMAL, mHandler); + mVendorSensorRegistered = true; + } + } + + private void stopListeningForVendorSensor() { + if (DEBUG) { + Log.d(TAG, "stopListeningForVendorSensor()"); + } + + if (mVendorSensorRegistered) { + mVendorSensorState = mLastVendorSensorState = VENDOR_SENSOR_UNKNOWN; + mSensorManager.unregisterListener(mVendorSensorListener); + mVendorSensorRegistered = false; + } + } + private void startListeningForProximity() { + + if (mVendorSensor != null) { + return; + } + if (DEBUG) { Log.d(TAG, "startListeningForProximity()"); } @@ -486,6 +565,11 @@ private void stopListeningForProximity() { } private void startListeningForLight() { + + if (mVendorSensor != null) { + return; + } + if (DEBUG) { Log.d(TAG, "startListeningForLight()"); } @@ -521,8 +605,10 @@ private void stopListeningForLight() { private void handleSystemReady() { if (DEBUG) { Log.d(TAG, "onBootPhase(): PHASE_SYSTEM_SERVICES_READY"); + Log.d(TAG, "onBootPhase(): VENDOR_SENSOR: " + mVendorPocketSensor); } mSystemReady = true; + if (mPending) { final Message msg = new Message(); msg.what = PocketHandler.MSG_INTERACTIVE_CHANGED; @@ -634,6 +720,42 @@ private void handleInteractiveChanged(boolean interactive) { update(); } + private void handleVendorSensorEvent(SensorEvent sensorEvent) { + final boolean isDeviceInPocket = isDeviceInPocket(); + + mLastVendorSensorState = mVendorSensorState; + + if (DEBUG) { + final String sensorEventToString = sensorEvent != null ? sensorEvent.toString() : "NULL"; + Log.d(TAG, "VENDOR_SENSOR: onSensorChanged(), sensorEvent =" + sensorEventToString); + } + + try { + if (sensorEvent == null) { + if (DEBUG) Log.d(TAG, "Event is null!"); + mVendorSensorState = VENDOR_SENSOR_UNKNOWN; + } else if (sensorEvent.values == null || sensorEvent.values.length == 0) { + if (DEBUG) Log.d(TAG, "Event has no values! event.values null ? " + (sensorEvent.values == null)); + mVendorSensorState = VENDOR_SENSOR_UNKNOWN; + } else { + final boolean isVendorPocket = sensorEvent.values[0] == 1.0; + if (DEBUG) { + final long time = SystemClock.uptimeMillis(); + Log.d(TAG, "Event: time=" + time + ", value=" + sensorEvent.values[0] + + ", isInPocket=" + isVendorPocket); + } + mVendorSensorState = isVendorPocket ? VENDOR_SENSOR_IN_POCKET : VENDOR_SENSOR_UNKNOWN; + } + } catch (NullPointerException e) { + Log.e(TAG, "Event: something went wrong, exception caught, e = " + e); + mVendorSensorState = VENDOR_SENSOR_UNKNOWN; + } finally { + if (isDeviceInPocket != isDeviceInPocket()) { + dispatchCallbacks(); + } + } + } + private void handleLightSensorEvent(SensorEvent sensorEvent) { final boolean isDeviceInPocket = isDeviceInPocket(); @@ -714,6 +836,15 @@ private void handleUnregisterTimeout() { unregisterSensorListeners(); } + private static Sensor getSensor(SensorManager sm, String type) { + for (Sensor sensor : sm.getSensorList(Sensor.TYPE_ALL)) { + if (type.equals(sensor.getStringType())) { + return sensor; + } + } + return null; + } + private void dispatchCallbacks() { final boolean isDeviceInPocket = isDeviceInPocket(); if (mInteractive) { @@ -742,6 +873,9 @@ private void dumpInternal(PrintWriter pw) { dump.put("lastLightState", mLastLightState); dump.put("lightRegistered", mLightRegistered); dump.put("lightMaxRange", mLightMaxRange); + dump.put("VendorSensorState", mVendorSensorState); + dump.put("lastVendorSensorState", mLastVendorSensorState); + dump.put("VendorSensorRegistered", mVendorSensorRegistered); } catch (JSONException e) { Slog.e(TAG, "dump formatting failure", e); } finally { From e2136a6c8198a86bad00f822a67eb78b8f190b3c Mon Sep 17 00:00:00 2001 From: jhenrique09 Date: Thu, 2 May 2019 21:35:51 -0300 Subject: [PATCH 04/51] PocketLock: Add config_pocketModeSupported overlay Change-Id: I6768c9f8cdd40b2a62df3bd9ddfa04022d69ce10 --- core/res/res/values/custom_config.xml | 3 +++ core/res/res/values/custom_symbols.xml | 1 + .../server/pocket/PocketBridgeService.java | 13 +++++++--- .../android/server/pocket/PocketService.java | 25 +++++++++++++++++-- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/core/res/res/values/custom_config.xml b/core/res/res/values/custom_config.xml index 5b20a03753e..b1fcef69339 100644 --- a/core/res/res/values/custom_config.xml +++ b/core/res/res/values/custom_config.xml @@ -221,4 +221,7 @@ + + true + diff --git a/core/res/res/values/custom_symbols.xml b/core/res/res/values/custom_symbols.xml index 4c620c96a6a..65d16e61f94 100644 --- a/core/res/res/values/custom_symbols.xml +++ b/core/res/res/values/custom_symbols.xml @@ -158,5 +158,6 @@ + diff --git a/services/core/java/com/android/server/pocket/PocketBridgeService.java b/services/core/java/com/android/server/pocket/PocketBridgeService.java index f57bf054036..5fc5e2721cc 100644 --- a/services/core/java/com/android/server/pocket/PocketBridgeService.java +++ b/services/core/java/com/android/server/pocket/PocketBridgeService.java @@ -73,6 +73,9 @@ public void onStateChanged(boolean isDeviceInPocket, int reason) { } }; + // Custom methods + private boolean mSupportedByDevice; + public PocketBridgeService(Context context) { super(context); mContext = context; @@ -81,9 +84,13 @@ public PocketBridgeService(Context context) { mHandler = new PocketBridgeHandler(handlerThread.getLooper()); mPocketManager = (PocketManager) context.getSystemService(Context.POCKET_SERVICE); + mSupportedByDevice = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_pocketModeSupported); mObserver = new PocketBridgeObserver(mHandler); - mObserver.onChange(true); - mObserver.register(); + if (mSupportedByDevice){ + mObserver.onChange(true); + mObserver.register(); + } } @Override @@ -98,7 +105,7 @@ private void setEnabled(boolean enabled) { } private void update() { - if (mPocketManager == null) return; + if (!mSupportedByDevice || mPocketManager == null) return; if (mEnabled) { mPocketManager.addCallback(mPocketCallback); diff --git a/services/core/java/com/android/server/pocket/PocketService.java b/services/core/java/com/android/server/pocket/PocketService.java index 3585e11bd43..5cfa5cf464e 100644 --- a/services/core/java/com/android/server/pocket/PocketService.java +++ b/services/core/java/com/android/server/pocket/PocketService.java @@ -162,6 +162,7 @@ public class PocketService extends SystemService implements IBinder.DeathRecipie // Custom methods private boolean mPocketLockVisible; + private boolean mSupportedByDevice; public PocketService(Context context) { super(context); @@ -181,9 +182,13 @@ public PocketService(Context context) { mLightMaxRange = mLightSensor.getMaximumRange(); } mVendorSensor = getSensor(mSensorManager, mVendorPocketSensor); + mSupportedByDevice = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_pocketModeSupported); mObserver = new PocketObserver(mHandler); - mObserver.onChange(true); - mObserver.register(); + if (mSupportedByDevice){ + mObserver.onChange(true); + mObserver.register(); + } } private class PocketObserver extends ContentObserver { @@ -452,6 +457,10 @@ public void onAccuracyChanged(Sensor sensor, int i) { } }; private boolean isDeviceInPocket() { + if (!mSupportedByDevice){ + return false; + } + if (mVendorSensorState != VENDOR_SENSOR_UNKNOWN) { return mVendorSensorState == VENDOR_SENSOR_IN_POCKET; } @@ -464,6 +473,9 @@ private boolean isDeviceInPocket() { } private void setEnabled(boolean enabled) { + if (!mSupportedByDevice){ + return; + } if (enabled != mEnabled) { mEnabled = enabled; mHandler.removeCallbacksAndMessages(null); @@ -472,6 +484,9 @@ private void setEnabled(boolean enabled) { } private void update() { + if (!mSupportedByDevice){ + return; + } if (!mEnabled || mInteractive) { if (mEnabled && isDeviceInPocket()) { // if device is judged to be in pocket while switching @@ -486,12 +501,18 @@ private void update() { } private void registerSensorListeners() { + if (!mSupportedByDevice){ + return; + } startListeningForVendorSensor(); startListeningForProximity(); startListeningForLight(); } private void unregisterSensorListeners() { + if (!mSupportedByDevice){ + return; + } stopListeningForVendorSensor(); stopListeningForProximity(); stopListeningForLight(); From 02846937ca19e6fd5dbf29862fedcba75f8d7ef8 Mon Sep 17 00:00:00 2001 From: Laker Date: Fri, 5 Feb 2021 19:43:44 +0300 Subject: [PATCH 05/51] PocketLock: Make using light sensor optional * On some devices using light sensor may break autobrightness Change-Id: I2bb4aad1ecc6808a4546dfdcada4335074d0d40e --- core/java/android/pocket/PocketConstants.java | 6 ------ core/res/res/values/custom_config.xml | 1 + core/res/res/values/custom_symbols.xml | 1 + .../core/java/com/android/server/pocket/PocketService.java | 4 +++- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/core/java/android/pocket/PocketConstants.java b/core/java/android/pocket/PocketConstants.java index f0d08a27237..70aa74a7f2a 100644 --- a/core/java/android/pocket/PocketConstants.java +++ b/core/java/android/pocket/PocketConstants.java @@ -16,10 +16,4 @@ public class PocketConstants { */ public static final boolean ENABLE_PROXIMITY_JUDGE = true; - /** - * Whether to use light sensor to evaluate pocket state. - */ - public static final boolean ENABLE_LIGHT_JUDGE = true; - - } diff --git a/core/res/res/values/custom_config.xml b/core/res/res/values/custom_config.xml index b1fcef69339..e9e6b2db344 100644 --- a/core/res/res/values/custom_config.xml +++ b/core/res/res/values/custom_config.xml @@ -223,5 +223,6 @@ true + true diff --git a/core/res/res/values/custom_symbols.xml b/core/res/res/values/custom_symbols.xml index 65d16e61f94..2c9f7a1c563 100644 --- a/core/res/res/values/custom_symbols.xml +++ b/core/res/res/values/custom_symbols.xml @@ -159,5 +159,6 @@ + diff --git a/services/core/java/com/android/server/pocket/PocketService.java b/services/core/java/com/android/server/pocket/PocketService.java index 5cfa5cf464e..44f964c9788 100644 --- a/services/core/java/com/android/server/pocket/PocketService.java +++ b/services/core/java/com/android/server/pocket/PocketService.java @@ -586,6 +586,8 @@ private void stopListeningForProximity() { } private void startListeningForLight() { + boolean mUseLightSensor = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_pocketUseLightSensor); if (mVendorSensor != null) { return; @@ -595,7 +597,7 @@ private void startListeningForLight() { Log.d(TAG, "startListeningForLight()"); } - if (!PocketConstants.ENABLE_LIGHT_JUDGE) { + if (!mUseLightSensor) { return; } From a8401da6f0ccdbd6eb76636f6e0cd3604d0f5aaa Mon Sep 17 00:00:00 2001 From: Hikari-no-Tenshi Date: Sat, 10 Jul 2021 22:21:34 +0300 Subject: [PATCH 06/51] PocketJudge: Allow to register vendor proximity sensor Some devices (ie OnePlus) have bunch of proximity sensors and default one may not work properly. This change allow to use particular proximity sensor. Example for OnePlus infrared proximity sensor: oneplus.sensor.infrared.proximity Change-Id: Ifc6411966338a5d8aaa5144d1d56954e8d98175c --- core/res/res/values/custom_config.xml | 1 + core/res/res/values/custom_symbols.xml | 1 + .../java/com/android/server/pocket/PocketService.java | 8 +++++++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/core/res/res/values/custom_config.xml b/core/res/res/values/custom_config.xml index e9e6b2db344..0eda77e70c5 100644 --- a/core/res/res/values/custom_config.xml +++ b/core/res/res/values/custom_config.xml @@ -220,6 +220,7 @@ + true diff --git a/core/res/res/values/custom_symbols.xml b/core/res/res/values/custom_symbols.xml index 2c9f7a1c563..c3e5de9f56d 100644 --- a/core/res/res/values/custom_symbols.xml +++ b/core/res/res/values/custom_symbols.xml @@ -158,6 +158,7 @@ + diff --git a/services/core/java/com/android/server/pocket/PocketService.java b/services/core/java/com/android/server/pocket/PocketService.java index 44f964c9788..28a757e5a7b 100644 --- a/services/core/java/com/android/server/pocket/PocketService.java +++ b/services/core/java/com/android/server/pocket/PocketService.java @@ -173,7 +173,13 @@ public PocketService(Context context) { mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); mVendorPocketSensor = mContext.getResources().getString( com.android.internal.R.string.config_pocketJudgeVendorSensorName); - mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); + String vendorProximitySensor = mContext.getResources().getString( + com.android.internal.R.string.config_pocketJudgeVendorProximitySensorName); + if (vendorProximitySensor != null && !vendorProximitySensor.isEmpty()) { + mProximitySensor = getSensor(mSensorManager, vendorProximitySensor); + } else { + mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); + } if (mProximitySensor != null) { mProximityMaxRange = mProximitySensor.getMaximumRange(); } From a96e8285d0d1ca22bd3637751b0a18af651a5a0d Mon Sep 17 00:00:00 2001 From: darknius09 Date: Fri, 30 Sep 2022 16:05:21 +0000 Subject: [PATCH 07/51] Revert "Pocket lock: Improve on fod devices" This reverts commit 10ee40d0a103296ce33307955edf7c8c909f2ec5. --- .../keyguard/KeyguardUpdateMonitor.java | 11 +----- .../systemui/biometrics/FODCircleView.java | 39 +------------------ 2 files changed, 3 insertions(+), 47 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index af8438e6211..14029eafc52 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -128,7 +128,6 @@ import javax.inject.Singleton; import com.android.internal.util.custom.faceunlock.FaceUnlockUtils; -import com.android.internal.util.custom.fod.FodUtils; import com.android.internal.util.custom.fod.FodUtils; @@ -334,8 +333,6 @@ public void onChanged(Integer ringer) { } }; - private boolean mHasFod; - private PocketManager mPocketManager; private boolean mIsDeviceInPocket; private final IPocketCallback mPocketCallback = new IPocketCallback.Stub() { @@ -711,9 +708,6 @@ private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiom private void handleFingerprintHelp(int msgId, String helpString) { Assert.isMainThread(); - if (mIsDeviceInPocket && mHasFod){ - return; - } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -1882,7 +1876,6 @@ public void handleMessage(Message msg) { } } } - mHasFod = FodUtils.hasFodSupport(mContext); } private final UserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() { @@ -2014,14 +2007,14 @@ private boolean shouldListenForFingerprint() { (mKeyguardOccluded && mIsDreaming)) && mDeviceInteractive && !mGoingToSleep && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser()) && (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser - && allowedOnBouncer && (mHasFod || !mIsDeviceInPocket); + && allowedOnBouncer && !mIsDeviceInPocket; } else { return (mKeyguardIsVisible || !mDeviceInteractive || (mBouncer && !mKeyguardGoingAway) || mGoingToSleep || shouldListenForFingerprintAssistant() || (mKeyguardOccluded && mIsDreaming)) && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser()) && (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser - && allowedOnBouncer && (mHasFod || !mIsDeviceInPocket); + && allowedOnBouncer && !mIsDeviceInPocket; } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FODCircleView.java b/packages/SystemUI/src/com/android/systemui/biometrics/FODCircleView.java index 3b73f399bf1..7176ea1aa63 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/FODCircleView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/FODCircleView.java @@ -45,8 +45,6 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; -import android.pocket.IPocketCallback; -import android.pocket.PocketManager; import android.provider.Settings; import android.net.Uri; import android.view.Display; @@ -279,7 +277,6 @@ public void onKeyguardVisibilityChanged(boolean showing) { if (mFODAnimation != null) { mFODAnimation.setAnimationKeyguard(mIsKeyguard); } - handlePocketManagerCallback(showing); } @Override @@ -355,20 +352,6 @@ public void onBiometricHelp(int msgId, String helpString, } }; - private void handlePocketManagerCallback(boolean keyguardShowing){ - if (!keyguardShowing){ - if (mPocketCallbackAdded){ - mPocketCallbackAdded = false; - mPocketManager.removeCallback(mPocketCallback); - } - }else{ - if (!mPocketCallbackAdded){ - mPocketCallbackAdded = true; - mPocketManager.addCallback(mPocketCallback); - } - } - } - private class FodGestureSettingsObserver extends ContentObserver { FodGestureSettingsObserver(Context context, Handler handler) { super(handler); @@ -441,23 +424,6 @@ void update() { private CustomSettingsObserver mCustomSettingsObserver; private FodGestureSettingsObserver mFodGestureSettingsObserver; - private PocketManager mPocketManager; - private boolean mIsDeviceInPocket; - private boolean mPocketCallbackAdded = false; - private final IPocketCallback mPocketCallback = new IPocketCallback.Stub() { - - @Override - public void onStateChanged(boolean isDeviceInPocket, int reason) { - boolean wasDeviceInPocket = mIsDeviceInPocket; - if (reason == PocketManager.REASON_SENSOR) { - mIsDeviceInPocket = isDeviceInPocket; - } else { - mIsDeviceInPocket = false; - } - } - - }; - public FODCircleView(Context context) { super(context); mContext = context; @@ -554,9 +520,6 @@ protected void onDraw(Canvas canvas) { updateCutoutFlags(); Dependency.get(ConfigurationController.class).addCallback(this); - - // Pocket - mPocketManager = (PocketManager) context.getSystemService(Context.POCKET_SERVICE); } private int interpolate(int i, int i2, int i3, int i4, int i5) { @@ -718,7 +681,7 @@ public void dispatchHide() { } public void showCircle() { - if (mFading || mTouchedOutside || (mIsKeyguard && mIsDeviceInPocket)) return; + if (mFading || mTouchedOutside) return; mIsCircleShowing = true; setKeepScreenOn(true); From 76ec3e3fef78b1c8df6f210a4b13bfbbed41e7ef Mon Sep 17 00:00:00 2001 From: palaych Date: Fri, 2 Sep 2022 08:16:33 +0900 Subject: [PATCH 08/51] base: Remove PixelPropsUtils Squash revert commits: commit 212eeec2fb927b04dde8f38b2ea684f349e44eb5 (HEAD) Author: palaych Date: Fri Sep 2 08:16:05 2022 +0900 Revert "Introduce PixelPropsUtils" This reverts commit 10d151880f95b838cad81fa3b43bcd268b31d7fd. commit d3a493c52a1393911b96e60112c3a3e53095ccfa Author: palaych Date: Fri Sep 2 08:16:05 2022 +0900 Revert "PixelPropsUtils: Override fingerprint for SettingsIntelligence" This reverts commit 6f5ecc6f55dc52e33a80f5f7d4516886cfb31ffb. commit 286d8ea58b8183072294cfad7866f8a434385d51 Author: palaych Date: Fri Sep 2 08:16:05 2022 +0900 Revert "PixelPropsUtils: Cleanup apps" This reverts commit c153795f9797fc2ff664c2039205929f45b76f86. commit 74e923585b18ffa3ada49188e4779b5c56e3f672 Author: palaych Date: Fri Sep 2 08:16:05 2022 +0900 Revert "PixelPropsUtils: bring back wallpaper collection" This reverts commit ef9f1a3a7b427b5e1e0b44cd520d8e6644b07792. commit 30916992884aebf766fe986e195be5418cf92d28 Author: palaych Date: Fri Sep 2 08:16:05 2022 +0900 Revert "PixelPropsUtils: Don't set build type/build debug props" This reverts commit 7828fb471854e35a60007f90350f1512fe1a7b20. commit 60f4478afb785f3ff8805ef99e1abfe27bcfdef2 Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "PixelPropsUtils: Change props to crosshatch" This reverts commit 80ead834d93b7a0ca1057016a01493ac352023a8. commit 6d55ee926393fc024eb31337b907045343cd7ce0 Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "PixelPropsUtils: Set pixel 5 props for specific apps" This reverts commit 46f375bfd0551b73576c26bf7a2769166d9836a2. commit 80a404924402cef91a345b33eaec55fdea0fb944 Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "PixelPropsUtils: Switch back to Pixel 5 props for all apps" This reverts commit 57e8f4782f3b7a79ca41b017cdfbb82ed48ddf68. commit 9fdc28d8badaf3c0152aacbf6345930e57888d36 Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "PixelPropsUtils: Set redfin build fingerprint" This reverts commit 83263054da49aaacd45b5bc01d315cbd21330388. commit 1b9a4a49e960aeb5da1b51a5b09315ab3aba845f Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "PixelPropsUtils: Update packages" This reverts commit 10e8819ac1734c6c6a1f6f54a3828bd946747bfc. commit bf85eb1f991702d603dd646fb8fa64f97f627583 Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "PixelPropsUtils: add Google Play Store to party as well" This reverts commit b1851e71bde9caa12ee81a815f07d3312111eebf. commit cac22fc79f58a78aefec223a8d8f1a18e9e02e0b Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "PixelPropsUtils: Spoof Pixel XL for Google Photos" This reverts commit 509d4ae5db873304690c7bef416d179cf62a6526. commit 095a4fa7ef9a0155e524905019daa51e0804d26a Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "PixelPropsUtils: Don't set model prop if gms" This reverts commit c785b20c3d7d5841e4dc56eaf33758fae59e7952. commit 58e64cfd687daf252e8962922a13b66396e9df60 Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "PixelPropsUtils: Update fingerprints" This reverts commit cabeea50680141b4e5f9f89e3428cc3a2f82a3cc. commit 969995530fd3329444ba298d0f315cfb2607abcf Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "PixelPropsUtils: Remove some packages" This reverts commit 6ae95a02bafa1fb2a7a82affdd9f7288caa4ccdf. commit dd9309658b355f6002c4dbf92ba6cdb0926a8791 Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "base: PixelPropsUtils: Update fp to RQ3A.211001.001" This reverts commit a828f7f8bf602dee27dce3c24510c9f2cac27076. commit 63464dfe5bde2bf9d33df274546039651e7bd8d5 Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "base: PixelPropsUtils: Update redfin fp to SP1A.211105.003" This reverts commit 58ed13dbb9e76396bc8c0125f10585c2c6538487. commit d5f8babf95f9097492e8ee86ac907012ff776cfd Author: palaych Date: Fri Sep 2 08:16:04 2022 +0900 Revert "base: PixelPropsUtils: Update redfin fp to SQ1A.211205.008" This reverts commit deb8d2d2d89b0a788b56e6f26752da156ddd3672. commit 6bede11bea04c6924a17eace32953f1f21766ea0 Author: palaych Date: Fri Sep 2 08:16:03 2022 +0900 Revert "base: PixelPropsUtils: Update redfin fp to SQ1A.220105.002" This reverts commit fc2aed638934a5f2d2575734578dbd5e7d83e72a. commit 7b2bd497cbec3ea0c7097dfeafec5008ff5bb526 Author: palaych Date: Fri Sep 2 08:16:03 2022 +0900 Revert "base: PixelPropsUtils: Update redfin fp to SQ1A.220205.002" This reverts commit 03546eaf08e9d3a4a99ea823eb8e539f4698c834. Change-Id: Ia13a86b20f2fc2a7fc5f6e06fdc3b89bc2f3cc73 --- core/java/com/android/internal/os/Zygote.java | 5 - .../internal/util/custom/PixelPropsUtils.java | 191 ------------------ 2 files changed, 196 deletions(-) delete mode 100644 core/java/com/android/internal/util/custom/PixelPropsUtils.java diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 29bc2886a17..ca7cec40b04 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -47,8 +47,6 @@ import java.io.IOException; import java.io.InputStreamReader; -import com.android.internal.util.custom.PixelPropsUtils; - /** @hide */ public final class Zygote { /* @@ -796,9 +794,6 @@ static void setAppProcessName(ZygoteArguments args, String loggingTag) { } else { Log.w(loggingTag, "Unable to set package name."); } - - // Set pixel props - PixelPropsUtils.setProps(args.mPackageName); } private static final String USAP_ERROR_PREFIX = "Invalid command to USAP: "; diff --git a/core/java/com/android/internal/util/custom/PixelPropsUtils.java b/core/java/com/android/internal/util/custom/PixelPropsUtils.java deleted file mode 100644 index 35e5bcc2694..00000000000 --- a/core/java/com/android/internal/util/custom/PixelPropsUtils.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2020 The Pixel Experience Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.internal.util.custom; - -import android.os.Build; -import android.util.Log; - -import java.util.Arrays; -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; - -public class PixelPropsUtils { - - private static final String TAG = PixelPropsUtils.class.getSimpleName(); - private static final boolean DEBUG = false; - - private static final Map propsToChangePixelXL; - private static final Map propsToChangePixel2; - private static final Map propsToChangePixel3XL; - private static final Map propsToChangePixel5a; - private static final Map propsToChangeOnePlus9Pro; - - private static final String[] packagesToChangePixelXL = { - "com.google.android.apps.photos", - "com.samsung.accessory.fridaymgr", - "com.samsung.accessory.berrymgr", - "com.samsung.accessory.neobeanmgr", - "com.samsung.android.app.watchmanager", - "com.samsung.android.geargplugin", - "com.samsung.android.gearnplugin", - "com.samsung.android.modenplugin", - "com.samsung.android.neatplugin", - "com.samsung.android.waterplugin" - }; - - private static final String[] packagesToChangePixel2 = { - "com.google.android.gms", - "com.google.android.gms.location.history" - }; - - private static final String[] packagesToChangePixel3XL = { - "com.google.android.googlequicksearchbox" - }; - - private static final String[] packagesToChangePixel5a = { - "com.breel.wallpapers20", - "com.google.android.apps.customization.pixel", - "com.google.android.apps.fitness", - "com.google.android.apps.maps", - "com.google.android.apps.recorder", - "com.google.android.apps.safetyhub", - "com.google.android.apps.subscriptions.red", - "com.google.android.apps.tachyon", - "com.google.android.apps.turbo", - "com.google.android.apps.turboadapter", - "com.google.android.apps.wallpaper", - "com.google.android.apps.wallpaper.pixel", - "com.google.android.as", - "com.google.android.dialer", - "com.google.android.inputmethod.latin", - "com.google.android.soundpicker", - "com.google.pixel.dynamicwallpapers", - "com.google.pixel.livewallpaper" - }; - - private static final String[] packagesToChangeOnePlus9Pro = { - "com.google.android.apps.wearables.maestro.companion" - }; - - static { - propsToChangePixelXL = new HashMap<>(); - propsToChangePixelXL.put("BRAND", "google"); - propsToChangePixelXL.put("MANUFACTURER", "Google"); - propsToChangePixelXL.put("DEVICE", "marlin"); - propsToChangePixelXL.put("PRODUCT", "marlin"); - propsToChangePixelXL.put("MODEL", "Pixel XL"); - propsToChangePixelXL.put("FINGERPRINT", "google/marlin/marlin:10/QP1A.191005.007.A3/5972272:user/release-keys"); - propsToChangePixel2 = new HashMap<>(); - propsToChangePixel2.put("BRAND", "google"); - propsToChangePixel2.put("MANUFACTURER", "Google"); - propsToChangePixel2.put("DEVICE", "walleye"); - propsToChangePixel2.put("PRODUCT", "walleye"); - propsToChangePixel2.put("MODEL", "Pixel 2"); - propsToChangePixel2.put("FINGERPRINT", "google/walleye/walleye:8.1.0/OPM1.171019.011/4448085:user/release-keys"); - propsToChangePixel3XL = new HashMap<>(); - propsToChangePixel3XL.put("BRAND", "google"); - propsToChangePixel3XL.put("MANUFACTURER", "Google"); - propsToChangePixel3XL.put("DEVICE", "crosshatch"); - propsToChangePixel3XL.put("PRODUCT", "crosshatch"); - propsToChangePixel3XL.put("MODEL", "Pixel 3 XL"); - propsToChangePixel3XL.put("FINGERPRINT", "google/crosshatch/crosshatch:11/RQ3A.210905.001/7511028:user/release-keys"); - propsToChangePixel5a = new HashMap<>(); - propsToChangePixel5a.put("BRAND", "google"); - propsToChangePixel5a.put("MANUFACTURER", "Google"); - propsToChangePixel5a.put("DEVICE", "barbet"); - propsToChangePixel5a.put("PRODUCT", "barbet"); - propsToChangePixel5a.put("MODEL", "Pixel 5a"); - propsToChangePixel5a.put("FINGERPRINT", "google/barbet/barbet:11/RD2A.210905.002/7513089:user/release-keys"); - propsToChangeOnePlus9Pro = new HashMap<>(); - propsToChangeOnePlus9Pro.put("BRAND", "OnePlus"); - propsToChangeOnePlus9Pro.put("MANUFACTURER", "OnePlus"); - propsToChangeOnePlus9Pro.put("DEVICE", "OnePlus9Pro"); - propsToChangeOnePlus9Pro.put("PRODUCT", "OnePlus9Pro_EEA"); - propsToChangeOnePlus9Pro.put("MODEL", "LE2123"); - propsToChangeOnePlus9Pro.put("FINGERPRINT", "OnePlus/OnePlus9Pro_EEA/OnePlus9Pro:11/RKQ1.201105.002/2107082109:user/release-keys"); - } - - public static void setProps(String packageName) { - if (packageName == null){ - return; - } - if (Arrays.asList(packagesToChangePixelXL).contains(packageName)){ - if (DEBUG){ - Log.d(TAG, "Defining props for: " + packageName); - } - for (Map.Entry prop : propsToChangePixelXL.entrySet()) { - String key = prop.getKey(); - Object value = prop.getValue(); - setPropValue(key, value); - } - } - if (Arrays.asList(packagesToChangePixel2).contains(packageName)){ - if (DEBUG){ - Log.d(TAG, "Defining props for: " + packageName); - } - for (Map.Entry prop : propsToChangePixel2.entrySet()) { - String key = prop.getKey(); - Object value = prop.getValue(); - setPropValue(key, value); - } - } - if (Arrays.asList(packagesToChangePixel3XL).contains(packageName)){ - if (DEBUG){ - Log.d(TAG, "Defining props for: " + packageName); - } - for (Map.Entry prop : propsToChangePixel3XL.entrySet()) { - String key = prop.getKey(); - Object value = prop.getValue(); - setPropValue(key, value); - } - } - if (Arrays.asList(packagesToChangePixel5a).contains(packageName)){ - if (DEBUG){ - Log.d(TAG, "Defining props for: " + packageName); - } - for (Map.Entry prop : propsToChangePixel5a.entrySet()) { - String key = prop.getKey(); - Object value = prop.getValue(); - setPropValue(key, value); - } - } - if (Arrays.asList(packagesToChangeOnePlus9Pro).contains(packageName)){ - if (DEBUG){ - Log.d(TAG, "Defining props for: " + packageName); - } - for (Map.Entry prop : propsToChangeOnePlus9Pro.entrySet()) { - String key = prop.getKey(); - Object value = prop.getValue(); - setPropValue(key, value); - } - } - } - - private static void setPropValue(String key, Object value){ - try { - if (DEBUG){ - Log.d(TAG, "Defining prop " + key + " to " + value.toString()); - } - Field field = Build.class.getDeclaredField(key); - field.setAccessible(true); - field.set(null, value); - field.setAccessible(false); - } catch (NoSuchFieldException | IllegalAccessException e) { - Log.e(TAG, "Failed to set prop " + key, e); - } - } -} \ No newline at end of file From e26f2a313b23a442b2d1c2bc8493717eaf584667 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Mon, 11 Oct 2021 19:59:51 -0700 Subject: [PATCH 09/51] base: Spoof build fingerprint for Google Play Services [1/2] SafetyNet's CTS profile attestation checks whether Build.FINGERPRINT matches that of the device's stock OS, which has passed CTS testing. Spoof the fingerprint for Google Play Services to help pass SafetyNet. NB: This code is under the gmscompat package, but it does not depend on any code from gmscompat. arrow edits: - Correct prop name for our logic. We are planning to use fp for different devices (like old oreo or follow new Pixel's). Signed-off-by: palaych Change-Id: I26a2498eb2e2163933303b03f6d516e5fb30fe51 --- core/java/android/app/Instrumentation.java | 3 + .../internal/gmscompat/AttestationHooks.java | 65 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 core/java/com/android/internal/gmscompat/AttestationHooks.java diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 721525d9af9..4b7d1ef6f34 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -56,6 +56,7 @@ import android.view.WindowManagerGlobal; import com.android.internal.content.ReferrerIntent; +import com.android.internal.gmscompat.AttestationHooks; import java.io.File; import java.lang.annotation.Retention; @@ -1157,6 +1158,7 @@ public Application newApplication(ClassLoader cl, String className, Context cont Application app = getFactory(context.getPackageName()) .instantiateApplication(cl, className); app.attach(context); + AttestationHooks.initApplicationBeforeOnCreate(app); return app; } @@ -1174,6 +1176,7 @@ static public Application newApplication(Class clazz, Context context) ClassNotFoundException { Application app = (Application)clazz.newInstance(); app.attach(context); + AttestationHooks.initApplicationBeforeOnCreate(app); return app; } diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java new file mode 100644 index 00000000000..95af2e9aa2d --- /dev/null +++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.gmscompat; + +import android.app.Application; +import android.os.Build; +import android.os.SystemProperties; +import android.util.Log; + +import java.lang.reflect.Field; + +/** @hide */ +public final class AttestationHooks { + private static final String TAG = "GmsCompat/Attestation"; + + private static final String PACKAGE_GMS = "com.google.android.gms"; + + private static final String PRODUCT_GMS_SPOOFING_FINGERPRINT = + SystemProperties.get("ro.build.gms_fingerprint"); + + private AttestationHooks() { } + + private static void setBuildField(String key, String value) { + try { + // Unlock + Field field = Build.class.getDeclaredField(key); + field.setAccessible(true); + + // Edit + field.set(null, value); + + // Lock + field.setAccessible(false); + } catch (NoSuchFieldException | IllegalAccessException e) { + Log.e(TAG, "Failed to spoof Build." + key, e); + } + } + + private static void spoofBuildGms() { + // Set fingerprint for SafetyNet CTS profile + if (PRODUCT_GMS_SPOOFING_FINGERPRINT.length() > 0) { + setBuildField("FINGERPRINT", PRODUCT_GMS_SPOOFING_FINGERPRINT); + } + } + + public static void initApplicationBeforeOnCreate(Application app) { + if (PACKAGE_GMS.equals(app.getPackageName())) { + spoofBuildGms(); + } + } +} From 9479f0d5fc451c863b76d2c0c7773f5f276f3966 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Mon, 11 Oct 2021 20:01:05 -0700 Subject: [PATCH 10/51] base: Alter model name to avoid SafetyNet HW attestation enforcement As of September 2, Google is enforcing SafetyNet's previously opportunistic hardware-backed attestation based on device information. Append a space to the device model name in order to avoid such enforcement. Change-Id: Ib7779e0aae40cab3730a56785e9231896917ab0a --- core/java/com/android/internal/gmscompat/AttestationHooks.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java index 95af2e9aa2d..409693c4d55 100644 --- a/core/java/com/android/internal/gmscompat/AttestationHooks.java +++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java @@ -55,6 +55,9 @@ private static void spoofBuildGms() { if (PRODUCT_GMS_SPOOFING_FINGERPRINT.length() > 0) { setBuildField("FINGERPRINT", PRODUCT_GMS_SPOOFING_FINGERPRINT); } + + // Alter model name to avoid hardware attestation enforcement + setBuildField("MODEL", Build.MODEL + " "); } public static void initApplicationBeforeOnCreate(Application app) { From 0987076142d6f3c1c6e5e6fbe12bcccdded57b4b Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Mon, 1 Nov 2021 20:06:48 -0700 Subject: [PATCH 11/51] base: Limit SafetyNet workarounds to unstable GMS process The unstable process is where SafetyNet attestation actually runs, so we only need to spoof the model in that process. Leaving other processes fixes various issues caused by model detection and flag provisioning, including screen-off Voice Match in Google Assistant, broken At a Glance weather and settings on Android 12, and more. Change-Id: Icfe2c34c357c833d8108cf6b5650214f32d273f5 --- .../com/android/internal/gmscompat/AttestationHooks.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java index 409693c4d55..bce97e6862d 100644 --- a/core/java/com/android/internal/gmscompat/AttestationHooks.java +++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java @@ -29,6 +29,8 @@ public final class AttestationHooks { private static final String PACKAGE_GMS = "com.google.android.gms"; + private static final String PROCESS_UNSTABLE = "com.google.android.gms.unstable"; + private static final String PRODUCT_GMS_SPOOFING_FINGERPRINT = SystemProperties.get("ro.build.gms_fingerprint"); @@ -61,7 +63,8 @@ private static void spoofBuildGms() { } public static void initApplicationBeforeOnCreate(Application app) { - if (PACKAGE_GMS.equals(app.getPackageName())) { + if (PACKAGE_GMS.equals(app.getPackageName()) && + PROCESS_UNSTABLE.equals(Application.getProcessName())) { spoofBuildGms(); } } From 553726483b8acbaca791b75b18c09c744a22eeac Mon Sep 17 00:00:00 2001 From: Albert I Date: Sun, 28 Aug 2022 02:12:19 +0900 Subject: [PATCH 12/51] core: pm: Wipe package cache on upgrade Squash commits: Author: Albert I Date: Thu May 12 05:37:43 2022 +0800 core: pm: Wipe package cache when upgrading system As we keep adding and removing features with each build, it's necessary to have package cache wiped out to avoid certain potential issues from arising due to a dirty flash. This commit is meant to supplement existing check for builds with incremental version that starts with "eng" (not eng build type, which skips generating package cache by design) which will continue to behave as expected. Signed-off-by: Albert I Author: Albert I Date: Fri Apr 8 18:59:52 2022 +0800 core: Wipe package cache on upgrade even on user build As we're spoofing builds by pretending it to be user, let's just do this for everyone. Signed-off-by: Albert I Change-Id: I5d967c25bd9c4890549d5d20f5e66b0c6845528c Author: Pranav Vashi Date: Thu Nov 14 01:40:35 2019 +0530 Restore cache clean up code in PackageManagerService * Forward ported to Android 10 Signed-off-by: Pranav Vashi Co-authored-by: Pranav Vashi Change-Id: Ieebe379853b69eb9268814169f58cf7794d8a0a5 --- .../core/java/com/android/server/pm/PackageManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 56d34391382..a752f85ad36 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4007,7 +4007,7 @@ private void updateInstantAppInstallerLocked(String modifiedPackage) { // NOTE: When no BUILD_NUMBER is set by the build system, it defaults to a build // that starts with "eng." to signify that this is an engineering build and not // destined for release. - if (Build.IS_USERDEBUG && Build.VERSION.INCREMENTAL.startsWith("eng.")) { + if (isUpgrade || Build.VERSION.INCREMENTAL.startsWith("eng.")) { Slog.w(TAG, "Wiping cache directory because the system partition changed."); // Heuristic: If the /system directory has been modified recently due to an "adb sync" From 25d6e8d55f561090cb2d1f0ede9852779213401e Mon Sep 17 00:00:00 2001 From: Manjeet Rulhania Date: Thu, 28 Apr 2022 21:50:25 +0000 Subject: [PATCH 13/51] Fix duplicate permission privilege escalation Duplicate permissions definition with different group allows privilege permission escalation to a different permission group. Android studio and gradle plugin does not allow duplicate permissions with different attributes, these tools only allow if duplicate permissions are exact copies. Also platform stores permissions in map at multiple places with permission name as key. This suggests that we can disallow duplicate permissions during package install/update Bug: 213323615 Test: AppSecurityTests Change-Id: I1910dca44104e35a57eba4acfa8188cd9b8626ac Merged-Id: I34120fff2ec2a158dfa55779d2afd4bbd49487ff Merged-In: I9bc839836786a0876e67fd73c05f8944bb532249 (cherry picked from commit f9a9dc720c151ce9d8a2bba6f5400f5a8f759b2d) Merged-In: I1910dca44104e35a57eba4acfa8188cd9b8626ac --- .../pm/parsing/ParsingPackageUtils.java | 8 +++ .../component/ParsedPermissionUtils.java | 49 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index 27016e8e3f0..2b8d3b63c12 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -21,6 +21,7 @@ import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_RESOURCES_ARSC_COMPRESSED; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; @@ -777,6 +778,13 @@ private ParseResult parseBaseApkTags(ParseInput input, ParsingPa ); } + if (ParsedPermissionUtils.declareDuplicatePermission(pkg)) { + return input.error( + INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Found duplicate permission with a different attribute value." + ); + } + convertNewPermissions(pkg); convertSplitPermissions(pkg); diff --git a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java index 1884a1e2783..9a6742c68ab 100644 --- a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java @@ -22,6 +22,8 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; +import android.util.ArrayMap; +import android.util.EventLog; import android.util.Slog; import com.android.internal.R; @@ -32,6 +34,8 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.util.List; +import java.util.Objects; /** @hide */ public class ParsedPermissionUtils { @@ -207,4 +211,49 @@ public static ParseResult parsePermissionGroup(ParsingPac return ComponentParseUtils.parseAllMetaData(pkg, res, parser, tag, permissionGroup, input); } + + /** + * Determines if a duplicate permission is malformed .i.e. defines different protection level + * or group. + */ + private static boolean isMalformedDuplicate(ParsedPermission p1, ParsedPermission p2) { + // Since a permission tree is also added as a permission with normal protection + // level, we need to skip if the parsedPermission is a permission tree. + if (p1 == null || p2 == null || p1.isTree() || p2.isTree()) { + return false; + } + + if (p1.getProtectionLevel() != p2.getProtectionLevel()) { + return true; + } + if (!Objects.equals(p1.getGroup(), p2.getGroup())) { + return true; + } + + return false; + } + + /** + * @return {@code true} if the package declares malformed duplicate permissions. + */ + public static boolean declareDuplicatePermission(@NonNull ParsingPackage pkg) { + final List permissions = pkg.getPermissions(); + final int size = permissions.size(); + if (size > 0) { + final ArrayMap checkDuplicatePerm = new ArrayMap<>(size); + for (int i = 0; i < size; i++) { + final ParsedPermission parsedPermission = permissions.get(i); + final String name = parsedPermission.getName(); + final ParsedPermission perm = checkDuplicatePerm.get(name); + if (isMalformedDuplicate(parsedPermission, perm)) { + // Fix for b/213323615 + EventLog.writeEvent(0x534e4554, "213323615", + "The package " + pkg.getPackageName() + " seems malicious"); + return true; + } + checkDuplicatePerm.put(name, parsedPermission); + } + } + return false; + } } From 74999479ae5673d47cbd7c90d7a81026e2038540 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Wed, 30 Mar 2022 21:46:29 +0000 Subject: [PATCH 14/51] Parcel: recycle recycles Before, it was like getting a used pan with food stuck on it. We run a clean ship here. You want a Parcel? You get a fresh Parcel. When we recycle a Parcel, we do a real clean-up job. Air freshener. All bits brushed over. These Parcel objects are clean as heck now! (specifically cleans mClassCookies) Bug: 208279300 Test: build Merged-In: I250872f5c6796bb64e2dc68008154c0e90feb218 Change-Id: I250872f5c6796bb64e2dc68008154c0e90feb218 (cherry picked from commit 46770fa49c9a5e51a5ea5a3afc7aab0dba2e59bd) (cherry picked from commit b5c79e141a81fa86fc834980d46886ac3c86ab11) Merged-In: I250872f5c6796bb64e2dc68008154c0e90feb218 --- core/java/android/os/Parcel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index e5bab6fc923..5a4b22b8a91 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -443,6 +443,7 @@ public static Parcel obtain() { */ public final void recycle() { if (DEBUG_RECYCLE) mStack = null; + mClassCookies = null; freeBuffer(); final Parcel[] pool; From bc142d80a920ecdd1120745444d2078c82888051 Mon Sep 17 00:00:00 2001 From: Manjeet Rulhania Date: Thu, 30 Jun 2022 22:09:09 +0000 Subject: [PATCH 15/51] Remove package name from SafetyNet logs Bug: 213323615 Test: AppSecurityTests Change-Id: I993832e148636f1795ffe393c6dc74a08b9442f8 Merged-In: I8f823487ca16861a35135cfc3383fa2ce8258017 Merged-In: I4b61d13256ce0bfb8fc9d21db52ee78ce2097f14 (cherry picked from commit bbe2a118277d9b225a272c53e509fdeb2fe0a993) Merged-In: I993832e148636f1795ffe393c6dc74a08b9442f8 --- .../content/pm/parsing/component/ParsedPermissionUtils.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java index 9a6742c68ab..fa7cfceb1a4 100644 --- a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java @@ -247,8 +247,7 @@ public static boolean declareDuplicatePermission(@NonNull ParsingPackage pkg) { final ParsedPermission perm = checkDuplicatePerm.get(name); if (isMalformedDuplicate(parsedPermission, perm)) { // Fix for b/213323615 - EventLog.writeEvent(0x534e4554, "213323615", - "The package " + pkg.getPackageName() + " seems malicious"); + EventLog.writeEvent(0x534e4554, "213323615"); return true; } checkDuplicatePerm.put(name, parsedPermission); From a79deb94b23d5cc1cbfa8645a1a0e39bb757b65f Mon Sep 17 00:00:00 2001 From: Adithya R Date: Thu, 8 Sep 2022 16:30:48 +0530 Subject: [PATCH 16/51] base: AttestationHooks: Spoof device as Pixel XL for Google Photos Enables unlimited photos and videos backup (restored functionality from PixelPropsUtils). Make this optional via overlay, as it needs to be disabled on some devices such as Pixel 6 series in order to utilize its tensor features. Squashed: Author: ReallySnow Date: Fri Dec 31 16:40:23 2021 +0800 core: Blacklist Pixel 2017 and 2018 exclusive for Google Photos * In this way can use PixelPropsUtils to simulate the Pixel XL prop method to use the unlimited storage space of Google Photos * Thanks nullbytepl for the idea Change-Id: I92d472d319373d648365c8c63e301f1a915f8de9 Author: kondors1995 Date: Mon Dec 20 16:53:46 2021 +0000 core: Extend Pixel feature blacklist for Google Photos Turns out having these breaks Original quality backups. Since these indicate that the device is pixel 4 which in turn breaks device spoofing as OG pixel Change-Id: Ibc57af35ca7e7146b3a839a544476ef716f85925 Author: Kuba Wojciechowski Date: Fri Nov 5 01:52:51 2021 +0300 core: Blacklist P21 experience system feature from Google Photos We want to include the P21 experience flag to enable new features, however it seems like Google Photos uses it to decide whether to use the TPU tflite delegate. There doesn't seem to be any fallback so we need to make sure the feature is not exposed to the app so that a normal NNAPI/GPU delegate can be used instead. Test: Google Photos editor with PIXEL_2021_EXPERIENCE feature in product Signed-off-by: Kuba Wojciechowski Change-Id: I51a02f8347324c7a85f3136b802dce4cc4556ac5 Co-authored-by: Kuba Wojciechowski Co-authored-by: kondors1995 Co-authored-by: ReallySnow Change-Id: Ia785b7a004192c96d1c0abe58733fb8700d43e25 Signed-off-by: palaych Signed-off-by: Adithya R --- .../app/ApplicationPackageManager.java | 4 +- .../internal/gmscompat/AttestationHooks.java | 47 +++++++++++++++++++ core/res/res/values/custom_config.xml | 3 ++ core/res/res/values/custom_symbols.xml | 3 ++ 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index c9031b71165..4d4aa4a381f 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -101,6 +101,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.Immutable; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.gmscompat.AttestationHooks; import com.android.internal.os.SomeArgs; import com.android.internal.util.UserIcons; @@ -668,7 +669,8 @@ protected Boolean recompute(HasSystemFeatureQuery query) { @Override public boolean hasSystemFeature(String name, int version) { - return mHasSystemFeatureCache.query(new HasSystemFeatureQuery(name, version)); + return AttestationHooks.hasSystemFeature(name, + mHasSystemFeatureCache.query(new HasSystemFeatureQuery(name, version))); } /** @hide */ diff --git a/core/java/com/android/internal/gmscompat/AttestationHooks.java b/core/java/com/android/internal/gmscompat/AttestationHooks.java index bce97e6862d..041b41831b7 100644 --- a/core/java/com/android/internal/gmscompat/AttestationHooks.java +++ b/core/java/com/android/internal/gmscompat/AttestationHooks.java @@ -17,23 +17,59 @@ package com.android.internal.gmscompat; import android.app.Application; +import android.content.res.Resources; import android.os.Build; import android.os.SystemProperties; import android.util.Log; +import com.android.internal.R; + import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; /** @hide */ public final class AttestationHooks { private static final String TAG = "GmsCompat/Attestation"; private static final String PACKAGE_GMS = "com.google.android.gms"; + private static final String PACKAGE_GPHOTOS = "com.google.android.apps.photos"; private static final String PROCESS_UNSTABLE = "com.google.android.gms.unstable"; private static final String PRODUCT_GMS_SPOOFING_FINGERPRINT = SystemProperties.get("ro.build.gms_fingerprint"); + private static final Map sP1Props = new HashMap<>(); + static { + sP1Props.put("BRAND", "google"); + sP1Props.put("MANUFACTURER", "Google"); + sP1Props.put("DEVICE", "marlin"); + sP1Props.put("PRODUCT", "marlin"); + sP1Props.put("MODEL", "Pixel XL"); + sP1Props.put("FINGERPRINT", "google/marlin/marlin:10/QP1A.191005.007.A3/5972272:user/release-keys"); + } + + private static final String[] sFeaturesBlacklist = { + "PIXEL_2017_EXPERIENCE", + "PIXEL_2017_PRELOAD", + "PIXEL_2018_PRELOAD", + "PIXEL_2019_EXPERIENCE", + "PIXEL_2019_MIDYEAR_EXPERIENCE", + "PIXEL_2019_MIDYEAR_PRELOAD", + "PIXEL_2019_PRELOAD", + "PIXEL_2020_EXPERIENCE", + "PIXEL_2020_MIDYEAR_EXPERIENCE", + "PIXEL_2021_EXPERIENCE", + "PIXEL_2021_MIDYEAR_EXPERIENCE" + }; + + private static volatile boolean sIsPhotos = false; + + private static final boolean sSpoofPhotos = + Resources.getSystem().getBoolean(R.bool.config_spoofGooglePhotos); + private AttestationHooks() { } private static void setBuildField(String key, String value) { @@ -66,6 +102,17 @@ public static void initApplicationBeforeOnCreate(Application app) { if (PACKAGE_GMS.equals(app.getPackageName()) && PROCESS_UNSTABLE.equals(Application.getProcessName())) { spoofBuildGms(); + } else if (sSpoofPhotos && PACKAGE_GPHOTOS.equals(app.getPackageName())) { + sIsPhotos = true; + sP1Props.forEach((k, v) -> setBuildField(k, v)); + } + } + + public static boolean hasSystemFeature(String name, boolean def) { + if (sIsPhotos && def && + Arrays.stream(sFeaturesBlacklist).anyMatch(name::contains)) { + return false; } + return def; } } diff --git a/core/res/res/values/custom_config.xml b/core/res/res/values/custom_config.xml index 0eda77e70c5..822b586a072 100644 --- a/core/res/res/values/custom_config.xml +++ b/core/res/res/values/custom_config.xml @@ -226,4 +226,7 @@ true true + + true + diff --git a/core/res/res/values/custom_symbols.xml b/core/res/res/values/custom_symbols.xml index c3e5de9f56d..6bf638f0104 100644 --- a/core/res/res/values/custom_symbols.xml +++ b/core/res/res/values/custom_symbols.xml @@ -162,4 +162,7 @@ + + + From 869be13047d80ce9ba47103317d07dfbf6a53bc5 Mon Sep 17 00:00:00 2001 From: Jon Haus Date: Thu, 5 Jan 2017 00:20:06 +0100 Subject: [PATCH 17/51] Network Traffic [1/2] ----- abc ezio84: use O darkintensity api use arrows vectors from aosp net arrows commit (thanks @Mazda-- for this find!): https://github.com/ezio84/abc_frameworks_base/commit/ad71ae1fd09f9a7392ab2eba7b766c8b088319b4 fix visual glitch on statusbar expand (arrows showing and quickly hiding again) don't show arrows when no data remove unit settings (KB is good) remove interval (set to 1sec by def) and single arrow options don't get settings values again when not needed fix padding between arrows and speed values and expose the padding value code cleanup ----- Change-Id: I026f67caec69a09c0c1969a09fbe99aa6b6f0510 --- core/java/android/provider/Settings.java | 11 + .../stat_sys_network_traffic_updown.xml | 29 ++ packages/SystemUI/res/layout/status_bar.xml | 12 +- .../SystemUI/res/values/custom_dimens.xml | 5 + .../phone/PhoneStatusBarTransitions.java | 7 +- .../statusbar/policy/NetworkTraffic.java | 298 ++++++++++++++++++ 6 files changed, 358 insertions(+), 4 deletions(-) create mode 100644 packages/SystemUI/res/drawable/stat_sys_network_traffic_updown.xml create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 8b2fed10218..c4b1f81513e 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4703,6 +4703,17 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean */ public static final String FOD_ANIM = "fod_recognizing_animation_list"; + /** + * Wheter to show network traffic indicator in statusbar + * @hide + */ + public static final String NETWORK_TRAFFIC_STATE = "network_traffic_state"; + /** + * Network traffic inactivity threshold (default is 1 kBs) + * @hide + */ + public static final String NETWORK_TRAFFIC_AUTOHIDE_THRESHOLD = "network_traffic_autohide_threshold"; + /** * Show pointer location on screen? * 0 = no diff --git a/packages/SystemUI/res/drawable/stat_sys_network_traffic_updown.xml b/packages/SystemUI/res/drawable/stat_sys_network_traffic_updown.xml new file mode 100644 index 00000000000..4e0b63ceffe --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_network_traffic_updown.xml @@ -0,0 +1,29 @@ + + + + + + diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index 37d3091ddc9..e6ab710c642 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -112,13 +112,23 @@ android:gravity="center_horizontal|center_vertical"/> + + diff --git a/packages/SystemUI/res/values/custom_dimens.xml b/packages/SystemUI/res/values/custom_dimens.xml index 1ced556bc64..0f6f52f786d 100644 --- a/packages/SystemUI/res/values/custom_dimens.xml +++ b/packages/SystemUI/res/values/custom_dimens.xml @@ -106,4 +106,9 @@ 13.5dp 20dp + + + 8dp + 2dp + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java index 8f20034a17c..867bd1363e3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java @@ -31,7 +31,7 @@ public final class PhoneStatusBarTransitions extends BarTransitions { private final float mIconAlphaWhenOpaque; - private View mLeftSide, mStatusIcons, mBattery, mClock, mCenterClock, mRightClock; + private View mLeftSide, mStatusIcons, mBattery, mClock, mCenterClock, mRightClock, mNetworkTraffic; private Animator mCurrentAnimation; @@ -48,6 +48,7 @@ public PhoneStatusBarTransitions(PhoneStatusBarView statusBarView, View backgrou mClock = statusBarView.findViewById(R.id.clock); mCenterClock = statusBarView.findViewById(R.id.center_clock); mRightClock = statusBarView.findViewById(R.id.right_clock); + mNetworkTraffic = statusBarView.findViewById(R.id.networkTraffic); applyModeBackground(-1, getMode(), false /*animate*/); applyMode(getMode(), false /*animate*/); } @@ -94,6 +95,7 @@ private void applyMode(int mode, boolean animate) { animateTransitionTo(mClock, newAlphaBC), animateTransitionTo(mCenterClock, newAlphaBC), animateTransitionTo(mRightClock, newAlphaBC) + animateTransitionTo(mNetworkTraffic, newAlpha) ); if (isLightsOut(mode)) { anims.setDuration(LIGHTS_OUT_DURATION); @@ -104,9 +106,8 @@ private void applyMode(int mode, boolean animate) { mLeftSide.setAlpha(newAlpha); mStatusIcons.setAlpha(newAlpha); mBattery.setAlpha(newAlphaBC); - mClock.setAlpha(newAlphaBC); mCenterClock.setAlpha(newAlphaBC); mRightClock.setAlpha(newAlphaBC); - } + mNetworkTraffic.setAlpha(newAlpha); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java new file mode 100644 index 00000000000..165d248d7bd --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -0,0 +1,298 @@ +package com.android.systemui.statusbar.policy; + +import java.text.DecimalFormat; + +import android.content.BroadcastReceiver; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; +import android.database.ContentObserver; +import android.graphics.drawable.Drawable; +import android.graphics.PorterDuff.Mode; +import android.graphics.Rect; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.TrafficStats; +import android.net.Uri; +import android.os.Handler; +import android.os.UserHandle; +import android.os.Message; +import android.os.SystemClock; +import android.provider.Settings; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.View; +import android.widget.TextView; + +import com.android.systemui.Dependency; +import com.android.systemui.R; +import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver; +/* +* +* Seeing how an Integer object in java requires at least 16 Bytes, it seemed awfully wasteful +* to only use it for a single boolean. 32-bits is plenty of room for what we need it to do. +* +*/ +public class NetworkTraffic extends TextView implements DarkReceiver { + + private static final int INTERVAL = 1500; //ms + private static final int KB = 1024; + private static final int MB = KB * KB; + private static final int GB = MB * KB; + private static final String symbol = "B/s"; + + private static DecimalFormat decimalFormat = new DecimalFormat("##0.#"); + static { + decimalFormat.setMaximumIntegerDigits(3); + decimalFormat.setMaximumFractionDigits(1); + } + + private boolean mIsEnabled; + private boolean mAttached; + private long totalRxBytes; + private long totalTxBytes; + private long lastUpdateTime; + private int txtSize; + private int txtImgPadding; + private int mAutoHideThreshold; + private int mTintColor; + + private Handler mTrafficHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + long timeDelta = SystemClock.elapsedRealtime() - lastUpdateTime; + + if (timeDelta < INTERVAL * .95) { + if (msg.what != 1) { + // we just updated the view, nothing further to do + return; + } + if (timeDelta < 1) { + // Can't div by 0 so make sure the value displayed is minimal + timeDelta = Long.MAX_VALUE; + } + } + lastUpdateTime = SystemClock.elapsedRealtime(); + + // Calculate the data rate from the change in total bytes and time + long newTotalRxBytes = TrafficStats.getTotalRxBytes(); + long newTotalTxBytes = TrafficStats.getTotalTxBytes(); + long rxData = newTotalRxBytes - totalRxBytes; + long txData = newTotalTxBytes - totalTxBytes; + + if (shouldHide(rxData, txData, timeDelta)) { + setText(""); + setVisibility(View.GONE); + } else { + // Get information for uplink ready so the line return can be added + String output = formatOutput(timeDelta, txData, symbol); + // Ensure text size is where it needs to be + output += "\n"; + // Add information for downlink if it's called for + output += formatOutput(timeDelta, rxData, symbol); + + // Update view if there's anything new to show + if (! output.contentEquals(getText())) { + setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); + setText(output); + } + setVisibility(View.VISIBLE); + } + + // Post delayed message to refresh in ~1000ms + totalRxBytes = newTotalRxBytes; + totalTxBytes = newTotalTxBytes; + clearHandlerCallbacks(); + mTrafficHandler.postDelayed(mRunnable, INTERVAL); + } + + private String formatOutput(long timeDelta, long data, String symbol) { + long speed = (long)(data / (timeDelta / 1000F)); + if (speed < KB) { + return decimalFormat.format(speed) + symbol; + } else if (speed < MB) { + return decimalFormat.format(speed / (float)KB) + 'k' + symbol; + } else if (speed < GB) { + return decimalFormat.format(speed / (float)MB) + 'M' + symbol; + } + return decimalFormat.format(speed / (float)GB) + 'G' + symbol; + } + + private boolean shouldHide(long rxData, long txData, long timeDelta) { + long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; + long speedRxKB = (long)(rxData / (timeDelta / 1000f)) / KB; + return !getConnectAvailable() || + (speedRxKB < mAutoHideThreshold && + speedTxKB < mAutoHideThreshold); + } + }; + + private Runnable mRunnable = new Runnable() { + @Override + public void run() { + mTrafficHandler.sendEmptyMessage(0); + } + }; + + class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + void observe() { + ContentResolver resolver = mContext.getContentResolver(); + resolver.registerContentObserver(Settings.System + .getUriFor(Settings.System.NETWORK_TRAFFIC_STATE), false, + this, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.System + .getUriFor(Settings.System.NETWORK_TRAFFIC_AUTOHIDE_THRESHOLD), false, + this, UserHandle.USER_ALL); + } + + /* + * @hide + */ + @Override + public void onChange(boolean selfChange) { + setMode(); + updateSettings(); + } + } + + /* + * @hide + */ + public NetworkTraffic(Context context) { + this(context, null); + } + + /* + * @hide + */ + public NetworkTraffic(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + /* + * @hide + */ + public NetworkTraffic(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + final Resources resources = getResources(); + txtSize = resources.getDimensionPixelSize(R.dimen.net_traffic_multi_text_size); + txtImgPadding = resources.getDimensionPixelSize(R.dimen.net_traffic_txt_img_padding); + mTintColor = resources.getColor(android.R.color.white); + Handler mHandler = new Handler(); + SettingsObserver settingsObserver = new SettingsObserver(mHandler); + settingsObserver.observe(); + setMode(); + updateSettings(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!mAttached) { + mAttached = true; + IntentFilter filter = new IntentFilter(); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + mContext.registerReceiver(mIntentReceiver, filter, null, getHandler()); + } + Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this); + updateSettings(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mAttached) { + mContext.unregisterReceiver(mIntentReceiver); + mAttached = false; + } + Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this); + } + + private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action != null && action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + updateSettings(); + } + } + }; + + private boolean getConnectAvailable() { + ConnectivityManager connManager = + (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo network = (connManager != null) ? connManager.getActiveNetworkInfo() : null; + return network != null; + } + + private void updateSettings() { + if (mIsEnabled) { + if (getConnectAvailable()) { + if (mAttached) { + totalRxBytes = TrafficStats.getTotalRxBytes(); + lastUpdateTime = SystemClock.elapsedRealtime(); + mTrafficHandler.sendEmptyMessage(1); + } + updateTrafficDrawable(); + return; + } + } else { + clearHandlerCallbacks(); + } + setVisibility(View.GONE); + } + + private void setMode() { + ContentResolver resolver = mContext.getContentResolver(); + mIsEnabled = Settings.System.getIntForUser(resolver, + Settings.System.NETWORK_TRAFFIC_STATE, 1, + UserHandle.USER_CURRENT) == 1; + mAutoHideThreshold = Settings.System.getIntForUser(resolver, + Settings.System.NETWORK_TRAFFIC_AUTOHIDE_THRESHOLD, 1, + UserHandle.USER_CURRENT); + } + + private void clearHandlerCallbacks() { + mTrafficHandler.removeCallbacks(mRunnable); + mTrafficHandler.removeMessages(0); + mTrafficHandler.removeMessages(1); + } + + private void updateTrafficDrawable() { + int intTrafficDrawable; + if (mIsEnabled) { + intTrafficDrawable = R.drawable.stat_sys_network_traffic_updown; + } else { + intTrafficDrawable = 0; + } + if (intTrafficDrawable != 0) { + Drawable d = getContext().getDrawable(intTrafficDrawable); + d.setColorFilter(mTintColor, Mode.SRC_ATOP); + setCompoundDrawablePadding(txtImgPadding); + setCompoundDrawablesWithIntrinsicBounds(null, null, d, null); + } else { + setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + } + + public void onDensityOrFontScaleChanged() { + final Resources resources = getResources(); + txtSize = resources.getDimensionPixelSize(R.dimen.net_traffic_multi_text_size); + txtImgPadding = resources.getDimensionPixelSize(R.dimen.net_traffic_multi_text_size); + setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); + setCompoundDrawablePadding(txtImgPadding); + } + + @Override + public void onDarkChanged(Rect area, float darkIntensity, int tint) { + mTintColor = DarkIconDispatcher.getTint(area, this, tint); + setTextColor(mTintColor); + updateTrafficDrawable(); + } +} From 0c51001220648a80c5422d6490772cca5cb7ed75 Mon Sep 17 00:00:00 2001 From: ezio84 Date: Tue, 10 Apr 2018 01:34:09 +0200 Subject: [PATCH 18/51] Statusbar net monitor: stop the handler if screen is off no need to keep the net monitor working if screen is off and waste system / battery resources Change-Id: I977eee3b38d19a755b9e9a0b38c13e86aea433c5 --- .../android/systemui/statusbar/policy/NetworkTraffic.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index 165d248d7bd..b9dea305e0a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -198,6 +198,8 @@ protected void onAttachedToWindow() { mAttached = true; IntentFilter filter = new IntentFilter(); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + filter.addAction(Intent.ACTION_SCREEN_OFF); + filter.addAction(Intent.ACTION_SCREEN_ON); mContext.registerReceiver(mIntentReceiver, filter, null, getHandler()); } Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this); @@ -218,8 +220,11 @@ protected void onDetachedFromWindow() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (action != null && action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + if (action != null && action.equals(ConnectivityManager.CONNECTIVITY_ACTION) + || action.equals(Intent.ACTION_SCREEN_ON)) { updateSettings(); + } else if (action != null && action.equals(Intent.ACTION_SCREEN_OFF)) { + clearHandlerCallbacks(); } } }; From a07bf6da0e055270dbbf8aa029195e04abc20e0e Mon Sep 17 00:00:00 2001 From: ezio84 Date: Sun, 9 Dec 2018 20:17:58 +0100 Subject: [PATCH 19/51] Move net monitor to expanded statusbar header Preview: https://i.ibb.co/1TCCwV8/455010636-14778.jpg Actually, with notch or low dpi and more statusbar icons we have not so much space there to show the net monitor. A notch can hide it and the system can now handle only a fixed max number of notifications and status icons, so when net monitor shows itself it can force the system to drop some icons to show the infamous dot. Let's also consider we usually check the monitor to see if the data transfer is working as expected and the speed is proper, so it's not an info we want to see always (it's also distracting when reading something). So, let's move it to expanded statusbar. There we have also some room to add line spacing and more info. Change-Id: I3fca786aec4f27c763e70d404448bd71dfaecceb --- .../quick_status_bar_header_system_icons.xml | 17 +++++++++++++--- packages/SystemUI/res/layout/status_bar.xml | 12 +---------- .../phone/PhoneStatusBarTransitions.java | 5 +---- .../statusbar/policy/NetworkTraffic.java | 20 +++++-------------- 4 files changed, 21 insertions(+), 33 deletions(-) diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml index 24dd7af329f..2ef358fd36e 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml @@ -48,12 +48,23 @@ systemui:showDark="false" /> - + android:layout_weight="1" + android:gravity="center_vertical|center_horizontal" /> + + - - diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java index 867bd1363e3..8bdc5abfbb3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java @@ -31,7 +31,7 @@ public final class PhoneStatusBarTransitions extends BarTransitions { private final float mIconAlphaWhenOpaque; - private View mLeftSide, mStatusIcons, mBattery, mClock, mCenterClock, mRightClock, mNetworkTraffic; + private View mLeftSide, mStatusIcons, mBattery, mClock, mCenterClock, mRightClock; private Animator mCurrentAnimation; @@ -48,7 +48,6 @@ public PhoneStatusBarTransitions(PhoneStatusBarView statusBarView, View backgrou mClock = statusBarView.findViewById(R.id.clock); mCenterClock = statusBarView.findViewById(R.id.center_clock); mRightClock = statusBarView.findViewById(R.id.right_clock); - mNetworkTraffic = statusBarView.findViewById(R.id.networkTraffic); applyModeBackground(-1, getMode(), false /*animate*/); applyMode(getMode(), false /*animate*/); } @@ -95,7 +94,6 @@ private void applyMode(int mode, boolean animate) { animateTransitionTo(mClock, newAlphaBC), animateTransitionTo(mCenterClock, newAlphaBC), animateTransitionTo(mRightClock, newAlphaBC) - animateTransitionTo(mNetworkTraffic, newAlpha) ); if (isLightsOut(mode)) { anims.setDuration(LIGHTS_OUT_DURATION); @@ -108,6 +106,5 @@ private void applyMode(int mode, boolean animate) { mBattery.setAlpha(newAlphaBC); mCenterClock.setAlpha(newAlphaBC); mRightClock.setAlpha(newAlphaBC); - mNetworkTraffic.setAlpha(newAlpha); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index b9dea305e0a..545eb0bb0b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -26,16 +26,15 @@ import android.view.View; import android.widget.TextView; -import com.android.systemui.Dependency; import com.android.systemui.R; -import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver; + /* * * Seeing how an Integer object in java requires at least 16 Bytes, it seemed awfully wasteful * to only use it for a single boolean. 32-bits is plenty of room for what we need it to do. * */ -public class NetworkTraffic extends TextView implements DarkReceiver { +public class NetworkTraffic extends TextView { private static final int INTERVAL = 1500; //ms private static final int KB = 1024; @@ -87,14 +86,14 @@ public void handleMessage(Message msg) { setVisibility(View.GONE); } else { // Get information for uplink ready so the line return can be added - String output = formatOutput(timeDelta, txData, symbol); + String output = "UL: " + formatOutput(timeDelta, txData, symbol); // Ensure text size is where it needs to be output += "\n"; // Add information for downlink if it's called for - output += formatOutput(timeDelta, rxData, symbol); + output += "DL: " + formatOutput(timeDelta, rxData, symbol); // Update view if there's anything new to show - if (! output.contentEquals(getText())) { + if (!output.contentEquals(getText())) { setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); setText(output); } @@ -202,7 +201,6 @@ protected void onAttachedToWindow() { filter.addAction(Intent.ACTION_SCREEN_ON); mContext.registerReceiver(mIntentReceiver, filter, null, getHandler()); } - Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this); updateSettings(); } @@ -213,7 +211,6 @@ protected void onDetachedFromWindow() { mContext.unregisterReceiver(mIntentReceiver); mAttached = false; } - Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this); } private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @@ -293,11 +290,4 @@ public void onDensityOrFontScaleChanged() { setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); setCompoundDrawablePadding(txtImgPadding); } - - @Override - public void onDarkChanged(Rect area, float darkIntensity, int tint) { - mTintColor = DarkIconDispatcher.getTint(area, this, tint); - setTextColor(mTintColor); - updateTrafficDrawable(); - } } From 73ed20476aec621c3ede54cddc93dec482173c10 Mon Sep 17 00:00:00 2001 From: ezio84 Date: Wed, 12 Dec 2018 19:42:08 +0100 Subject: [PATCH 20/51] Net monitor: fix text color on light theme Change-Id: I5c4d7a3c5fdc626fe8b34c88212ed01154b3ab65 --- .../SystemUI/res/layout/quick_status_bar_header_system_icons.xml | 1 + .../com/android/systemui/statusbar/policy/NetworkTraffic.java | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml index 2ef358fd36e..d72e0813fc7 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml @@ -64,6 +64,7 @@ android:layout_marginEnd="2dp" android:singleLine="false" android:lineSpacingMultiplier="1.2" + systemui:showDark="false" android:gravity="right|center_vertical"/> Date: Mon, 24 Dec 2018 15:03:44 +0100 Subject: [PATCH 21/51] Network traffic: fix indicator not hiding on lost connection With https://gerrit.aicp-rom.com/c/AICP/frameworks_base/+/80636 ("Statusbar net monitor: stop the handler if screen is off"), connectivity status can change without us noticing, so let's update in updateSettings() (which is called after turning the screen on) also if there is no connection. Change-Id: I674f9cc3946f679b1ff9696079c5608fdfaa12d7 --- .../systemui/statusbar/policy/NetworkTraffic.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index 6e746bb962a..547cef2a746 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -235,15 +235,13 @@ private boolean getConnectAvailable() { private void updateSettings() { if (mIsEnabled) { - if (getConnectAvailable()) { - if (mAttached) { - totalRxBytes = TrafficStats.getTotalRxBytes(); - lastUpdateTime = SystemClock.elapsedRealtime(); - mTrafficHandler.sendEmptyMessage(1); - } - updateTrafficDrawable(); - return; + if (mAttached) { + totalRxBytes = TrafficStats.getTotalRxBytes(); + lastUpdateTime = SystemClock.elapsedRealtime(); + mTrafficHandler.sendEmptyMessage(1); } + updateTrafficDrawable(); + return; } else { clearHandlerCallbacks(); } From e0440bc5f800f5936b642124e3ea7a68e820a71a Mon Sep 17 00:00:00 2001 From: Josh Chasky Date: Thu, 19 Dec 2019 15:13:04 -0500 Subject: [PATCH 22/51] Make sure that Network Traffic is disabled by default Change-Id: Ic78e82cedb676f99dd17ce88ba2e66173f000bdc --- .../com/android/systemui/statusbar/policy/NetworkTraffic.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index 547cef2a746..147f98a2f39 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -251,7 +251,7 @@ private void updateSettings() { private void setMode() { ContentResolver resolver = mContext.getContentResolver(); mIsEnabled = Settings.System.getIntForUser(resolver, - Settings.System.NETWORK_TRAFFIC_STATE, 1, + Settings.System.NETWORK_TRAFFIC_STATE, 0, UserHandle.USER_CURRENT) == 1; mAutoHideThreshold = Settings.System.getIntForUser(resolver, Settings.System.NETWORK_TRAFFIC_AUTOHIDE_THRESHOLD, 1, From 1c216127585f8ab2cad5c04205a00874ce168432 Mon Sep 17 00:00:00 2001 From: Alex Cruz Date: Sun, 13 Jan 2019 10:59:49 -0600 Subject: [PATCH 23/51] Network Traffic: Bring back traffic indicator for all Change-Id: Ia41474a262b258f8a2d4d7b10a15891729ffd17c --- packages/SystemUI/res/layout/status_bar.xml | 10 + .../phone/PhoneStatusBarTransitions.java | 9 +- .../statusbar/policy/NetworkTraffic.java | 6 +- .../statusbar/policy/NetworkTrafficSB.java | 312 ++++++++++++++++++ 4 files changed, 332 insertions(+), 5 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index 37d3091ddc9..bffb55ec881 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -119,6 +119,16 @@ android:gravity="center_vertical|end" > + + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java index 8bdc5abfbb3..acbd578fe97 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java @@ -22,6 +22,7 @@ import android.content.res.Resources; import android.view.View; +import com.android.internal.util.custom.CustomUtils; import com.android.systemui.R; public final class PhoneStatusBarTransitions extends BarTransitions { @@ -31,7 +32,7 @@ public final class PhoneStatusBarTransitions extends BarTransitions { private final float mIconAlphaWhenOpaque; - private View mLeftSide, mStatusIcons, mBattery, mClock, mCenterClock, mRightClock; + private View mLeftSide, mStatusIcons, mBattery, mClock, mCenterClock, mRightClock, mNetworkTraffic; private Animator mCurrentAnimation; @@ -48,6 +49,9 @@ public PhoneStatusBarTransitions(PhoneStatusBarView statusBarView, View backgrou mClock = statusBarView.findViewById(R.id.clock); mCenterClock = statusBarView.findViewById(R.id.center_clock); mRightClock = statusBarView.findViewById(R.id.right_clock); + mNetworkTraffic = statusBarView.findViewById(R.id.networkTraffic); + mNetworkTraffic.setVisibility( + CustomUtils.hasNotch(statusBarView.getContext()) ? View.GONE : View.VISIBLE); applyModeBackground(-1, getMode(), false /*animate*/); applyMode(getMode(), false /*animate*/); } @@ -94,6 +98,7 @@ private void applyMode(int mode, boolean animate) { animateTransitionTo(mClock, newAlphaBC), animateTransitionTo(mCenterClock, newAlphaBC), animateTransitionTo(mRightClock, newAlphaBC) + animateTransitionTo(mNetworkTraffic, newAlpha) ); if (isLightsOut(mode)) { anims.setDuration(LIGHTS_OUT_DURATION); @@ -106,5 +111,7 @@ private void applyMode(int mode, boolean animate) { mBattery.setAlpha(newAlphaBC); mCenterClock.setAlpha(newAlphaBC); mRightClock.setAlpha(newAlphaBC); + mNetworkTraffic.setAlpha(newAlpha); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index 147f98a2f39..ee1d9ca5c6e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -11,11 +11,9 @@ import android.database.ContentObserver; import android.graphics.drawable.Drawable; import android.graphics.PorterDuff.Mode; -import android.graphics.Rect; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.TrafficStats; -import android.net.Uri; import android.os.Handler; import android.os.UserHandle; import android.os.Message; @@ -86,11 +84,11 @@ public void handleMessage(Message msg) { setVisibility(View.GONE); } else { // Get information for uplink ready so the line return can be added - String output = "UL: " + formatOutput(timeDelta, txData, symbol); + String output = formatOutput(timeDelta, txData, symbol); // Ensure text size is where it needs to be output += "\n"; // Add information for downlink if it's called for - output += "DL: " + formatOutput(timeDelta, rxData, symbol); + output += formatOutput(timeDelta, rxData, symbol); // Update view if there's anything new to show if (!output.contentEquals(getText())) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java new file mode 100644 index 00000000000..fdcd4b98df8 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java @@ -0,0 +1,312 @@ +package com.android.systemui.statusbar.policy; + +import java.text.DecimalFormat; + +import android.content.BroadcastReceiver; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; +import android.database.ContentObserver; +import android.graphics.drawable.Drawable; +import android.graphics.PorterDuff.Mode; +import android.graphics.Rect; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.TrafficStats; +import android.os.Handler; +import android.os.UserHandle; +import android.os.Message; +import android.os.SystemClock; +import android.provider.Settings; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.View; +import android.widget.TextView; + +import com.android.internal.util.arrow.ArrowUtils; + +import com.android.systemui.Dependency; +import com.android.systemui.plugins.DarkIconDispatcher; +import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; +import com.android.systemui.R; + +/* +* +* Seeing how an Integer object in java requires at least 16 Bytes, it seemed awfully wasteful +* to only use it for a single boolean. 32-bits is plenty of room for what we need it to do. +* +*/ +public class NetworkTrafficSB extends TextView implements DarkReceiver { + + private static final int INTERVAL = 1500; //ms + private static final int KB = 1024; + private static final int MB = KB * KB; + private static final int GB = MB * KB; + private static final String symbol = "B/s"; + + private static DecimalFormat decimalFormat = new DecimalFormat("##0.#"); + static { + decimalFormat.setMaximumIntegerDigits(3); + decimalFormat.setMaximumFractionDigits(1); + } + + private boolean mIsEnabled; + private boolean mAttached; + private long totalRxBytes; + private long totalTxBytes; + private long lastUpdateTime; + private int txtSize; + private int txtImgPadding; + private int mAutoHideThreshold; + private int mTintColor; + + private boolean mScreenOn = true; + + private Handler mTrafficHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + long timeDelta = SystemClock.elapsedRealtime() - lastUpdateTime; + + if (timeDelta < INTERVAL * .95) { + if (msg.what != 1) { + // we just updated the view, nothing further to do + return; + } + if (timeDelta < 1) { + // Can't div by 0 so make sure the value displayed is minimal + timeDelta = Long.MAX_VALUE; + } + } + lastUpdateTime = SystemClock.elapsedRealtime(); + + // Calculate the data rate from the change in total bytes and time + long newTotalRxBytes = TrafficStats.getTotalRxBytes(); + long newTotalTxBytes = TrafficStats.getTotalTxBytes(); + long rxData = newTotalRxBytes - totalRxBytes; + long txData = newTotalTxBytes - totalTxBytes; + + if (shouldHide(rxData, txData, timeDelta)) { + setText(""); + setVisibility(View.GONE); + } else { + // Get information for uplink ready so the line return can be added + String output = formatOutput(timeDelta, txData, symbol); + // Ensure text size is where it needs to be + output += "\n"; + // Add information for downlink if it's called for + output += formatOutput(timeDelta, rxData, symbol); + + // Update view if there's anything new to show + if (!output.contentEquals(getText())) { + setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); + setText(output); + } + setVisibility(ArrowUtils.hasNotch(mContext) ? View.GONE : View.VISIBLE); + } + + // Post delayed message to refresh in ~1000ms + totalRxBytes = newTotalRxBytes; + totalTxBytes = newTotalTxBytes; + clearHandlerCallbacks(); + mTrafficHandler.postDelayed(mRunnable, INTERVAL); + } + + private String formatOutput(long timeDelta, long data, String symbol) { + long speed = (long)(data / (timeDelta / 1000F)); + if (speed < KB) { + return decimalFormat.format(speed) + symbol; + } else if (speed < MB) { + return decimalFormat.format(speed / (float)KB) + 'k' + symbol; + } else if (speed < GB) { + return decimalFormat.format(speed / (float)MB) + 'M' + symbol; + } + return decimalFormat.format(speed / (float)GB) + 'G' + symbol; + } + + private boolean shouldHide(long rxData, long txData, long timeDelta) { + long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; + long speedRxKB = (long)(rxData / (timeDelta / 1000f)) / KB; + return !getConnectAvailable() || + (speedRxKB < mAutoHideThreshold && + speedTxKB < mAutoHideThreshold); + } + }; + + private Runnable mRunnable = new Runnable() { + @Override + public void run() { + mTrafficHandler.sendEmptyMessage(0); + } + }; + + class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + void observe() { + ContentResolver resolver = mContext.getContentResolver(); + resolver.registerContentObserver(Settings.System + .getUriFor(Settings.System.NETWORK_TRAFFIC_STATE), false, + this, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.System + .getUriFor(Settings.System.NETWORK_TRAFFIC_AUTOHIDE_THRESHOLD), false, + this, UserHandle.USER_ALL); + } + + /* + * @hide + */ + @Override + public void onChange(boolean selfChange) { + setMode(); + updateSettings(); + } + } + + /* + * @hide + */ + public NetworkTrafficSB(Context context) { + this(context, null); + } + + /* + * @hide + */ + public NetworkTrafficSB(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + /* + * @hide + */ + public NetworkTrafficSB(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + final Resources resources = getResources(); + txtSize = resources.getDimensionPixelSize(R.dimen.net_traffic_multi_text_size); + txtImgPadding = resources.getDimensionPixelSize(R.dimen.net_traffic_txt_img_padding); + mTintColor = resources.getColor(android.R.color.white); + Handler mHandler = new Handler(); + SettingsObserver settingsObserver = new SettingsObserver(mHandler); + settingsObserver.observe(); + setMode(); + updateSettings(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!mAttached) { + mAttached = true; + IntentFilter filter = new IntentFilter(); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + filter.addAction(Intent.ACTION_SCREEN_OFF); + filter.addAction(Intent.ACTION_SCREEN_ON); + mContext.registerReceiver(mIntentReceiver, filter, null, getHandler()); + } + Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this); + updateSettings(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mAttached) { + mContext.unregisterReceiver(mIntentReceiver); + mAttached = false; + } + Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this); + } + + private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action == null) return; + + if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) && mScreenOn) { + updateSettings(); + } else if (action.equals(Intent.ACTION_SCREEN_ON)) { + mScreenOn = true; + updateSettings(); + } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { + mScreenOn = false; + clearHandlerCallbacks(); + } + } + }; + + private boolean getConnectAvailable() { + ConnectivityManager connManager = + (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo network = (connManager != null) ? connManager.getActiveNetworkInfo() : null; + return network != null; + } + + private void updateSettings() { + if (mIsEnabled) { + if (mAttached) { + totalRxBytes = TrafficStats.getTotalRxBytes(); + lastUpdateTime = SystemClock.elapsedRealtime(); + mTrafficHandler.sendEmptyMessage(1); + } + updateTrafficDrawable(); + return; + } else { + clearHandlerCallbacks(); + } + setVisibility(View.GONE); + } + + private void setMode() { + ContentResolver resolver = mContext.getContentResolver(); + mIsEnabled = Settings.System.getIntForUser(resolver, + Settings.System.NETWORK_TRAFFIC_STATE, 0, + UserHandle.USER_CURRENT) == 1; + mAutoHideThreshold = Settings.System.getIntForUser(resolver, + Settings.System.NETWORK_TRAFFIC_AUTOHIDE_THRESHOLD, 0, + UserHandle.USER_CURRENT); + } + + private void clearHandlerCallbacks() { + mTrafficHandler.removeCallbacks(mRunnable); + mTrafficHandler.removeMessages(0); + mTrafficHandler.removeMessages(1); + } + + private void updateTrafficDrawable() { + int intTrafficDrawable; + if (mIsEnabled) { + intTrafficDrawable = R.drawable.stat_sys_network_traffic_updown; + } else { + intTrafficDrawable = 0; + } + if (intTrafficDrawable != 0) { + Drawable d = getContext().getDrawable(intTrafficDrawable); + d.setColorFilter(mTintColor, Mode.SRC_ATOP); + setCompoundDrawablePadding(txtImgPadding); + setCompoundDrawablesWithIntrinsicBounds(null, null, d, null); + } else { + setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + setTextColor(mTintColor); + } + + public void onDensityOrFontScaleChanged() { + final Resources resources = getResources(); + txtSize = resources.getDimensionPixelSize(R.dimen.net_traffic_multi_text_size); + txtImgPadding = resources.getDimensionPixelSize(R.dimen.net_traffic_multi_text_size); + setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); + setCompoundDrawablePadding(txtImgPadding); + } + + @Override + public void onDarkChanged(Rect area, float darkIntensity, int tint) { + mTintColor = DarkIconDispatcher.getTint(area, this, tint); + setTextColor(mTintColor); + updateTrafficDrawable(); + } +} From f8cc58f6342cd49a37b0e93888446094d8d72f42 Mon Sep 17 00:00:00 2001 From: Michele Bono Date: Mon, 17 Dec 2018 22:39:55 -0600 Subject: [PATCH 24/51] Network Traffic: Move network indicator to the right singleLine is deprecated use maxLines instead Follow system font Change-Id: Ib739bdca613be43411a0822bbee86013c48e2bd7 --- packages/SystemUI/res/layout/status_bar.xml | 10 ---------- packages/SystemUI/res/layout/system_icons.xml | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index bffb55ec881..37d3091ddc9 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -119,16 +119,6 @@ android:gravity="center_vertical|end" > - - diff --git a/packages/SystemUI/res/layout/system_icons.xml b/packages/SystemUI/res/layout/system_icons.xml index 818d1d77177..c80be5fc8c8 100644 --- a/packages/SystemUI/res/layout/system_icons.xml +++ b/packages/SystemUI/res/layout/system_icons.xml @@ -21,9 +21,23 @@ android:layout_height="match_parent" android:gravity="center_vertical"> - + + + + Date: Tue, 12 Mar 2019 16:01:38 +0100 Subject: [PATCH 25/51] Network Traffic: OOS style network traffic indicator - add separate dimens. values for SBtraffic - adjust size and alignment - reduce left right padding - make traffic text bold/font - set gravity to right - nuked arrow indicators - upload and download speeds view switch depending on which is higher Change-Id: I48a16dc383ce333f0a64aa87b994d300b26e6a9c --- .../SystemUI/res/values/custom_dimens.xml | 2 +- .../statusbar/policy/NetworkTrafficSB.java | 56 ++++++++++--------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/packages/SystemUI/res/values/custom_dimens.xml b/packages/SystemUI/res/values/custom_dimens.xml index 0f6f52f786d..45e0115553f 100644 --- a/packages/SystemUI/res/values/custom_dimens.xml +++ b/packages/SystemUI/res/values/custom_dimens.xml @@ -108,7 +108,7 @@ 20dp + 13dp 8dp 2dp - diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java index fdcd4b98df8..31ff00adfd4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java @@ -12,6 +12,8 @@ import android.graphics.drawable.Drawable; import android.graphics.PorterDuff.Mode; import android.graphics.Rect; +import android.graphics.Typeface; +import android.view.Gravity; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.TrafficStats; @@ -44,7 +46,7 @@ public class NetworkTrafficSB extends TextView implements DarkReceiver { private static final int KB = 1024; private static final int MB = KB * KB; private static final int GB = MB * KB; - private static final String symbol = "B/s"; + private static final String symbol = "/s"; private static DecimalFormat decimalFormat = new DecimalFormat("##0.#"); static { @@ -58,7 +60,6 @@ public class NetworkTrafficSB extends TextView implements DarkReceiver { private long totalTxBytes; private long lastUpdateTime; private int txtSize; - private int txtImgPadding; private int mAutoHideThreshold; private int mTintColor; @@ -90,17 +91,26 @@ public void handleMessage(Message msg) { if (shouldHide(rxData, txData, timeDelta)) { setText(""); setVisibility(View.GONE); - } else { - // Get information for uplink ready so the line return can be added + } else if (shouldShowUpload(rxData, txData, timeDelta)) { + // Show information for uplink if it's called for String output = formatOutput(timeDelta, txData, symbol); - // Ensure text size is where it needs to be - output += "\n"; + + // Update view if there's anything new to show + if (!output.contentEquals(getText())) { + setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); + setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); + setGravity(Gravity.RIGHT); + setText(output); + } + } else { // Add information for downlink if it's called for - output += formatOutput(timeDelta, rxData, symbol); + String output = formatOutput(timeDelta, rxData, symbol); // Update view if there's anything new to show if (!output.contentEquals(getText())) { setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); + setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); + setGravity(Gravity.RIGHT); setText(output); } setVisibility(ArrowUtils.hasNotch(mContext) ? View.GONE : View.VISIBLE); @@ -116,9 +126,9 @@ public void handleMessage(Message msg) { private String formatOutput(long timeDelta, long data, String symbol) { long speed = (long)(data / (timeDelta / 1000F)); if (speed < KB) { - return decimalFormat.format(speed) + symbol; + return decimalFormat.format(speed / (float)KB) + 'K' + symbol; } else if (speed < MB) { - return decimalFormat.format(speed / (float)KB) + 'k' + symbol; + return decimalFormat.format(speed / (float)KB) + 'K' + symbol; } else if (speed < GB) { return decimalFormat.format(speed / (float)MB) + 'M' + symbol; } @@ -126,12 +136,19 @@ private String formatOutput(long timeDelta, long data, String symbol) { } private boolean shouldHide(long rxData, long txData, long timeDelta) { - long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; long speedRxKB = (long)(rxData / (timeDelta / 1000f)) / KB; + long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; return !getConnectAvailable() || (speedRxKB < mAutoHideThreshold && speedTxKB < mAutoHideThreshold); } + + private boolean shouldShowUpload(long rxData, long txData, long timeDelta) { + long speedRxKB = (long)(rxData / (timeDelta / 1000f)) / KB; + long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; + + return (speedTxKB > speedRxKB); + } }; private Runnable mRunnable = new Runnable() { @@ -186,8 +203,7 @@ public NetworkTrafficSB(Context context, AttributeSet attrs) { public NetworkTrafficSB(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); final Resources resources = getResources(); - txtSize = resources.getDimensionPixelSize(R.dimen.net_traffic_multi_text_size); - txtImgPadding = resources.getDimensionPixelSize(R.dimen.net_traffic_txt_img_padding); + txtSize = resources.getDimensionPixelSize(R.dimen.net_traffic_sb_multi_text_size); mTintColor = resources.getColor(android.R.color.white); Handler mHandler = new Handler(); SettingsObserver settingsObserver = new SettingsObserver(mHandler); @@ -280,16 +296,6 @@ private void clearHandlerCallbacks() { private void updateTrafficDrawable() { int intTrafficDrawable; if (mIsEnabled) { - intTrafficDrawable = R.drawable.stat_sys_network_traffic_updown; - } else { - intTrafficDrawable = 0; - } - if (intTrafficDrawable != 0) { - Drawable d = getContext().getDrawable(intTrafficDrawable); - d.setColorFilter(mTintColor, Mode.SRC_ATOP); - setCompoundDrawablePadding(txtImgPadding); - setCompoundDrawablesWithIntrinsicBounds(null, null, d, null); - } else { setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); } setTextColor(mTintColor); @@ -297,10 +303,10 @@ private void updateTrafficDrawable() { public void onDensityOrFontScaleChanged() { final Resources resources = getResources(); - txtSize = resources.getDimensionPixelSize(R.dimen.net_traffic_multi_text_size); - txtImgPadding = resources.getDimensionPixelSize(R.dimen.net_traffic_multi_text_size); + txtSize = resources.getDimensionPixelSize(R.dimen.net_traffic_sb_multi_text_size); setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); - setCompoundDrawablePadding(txtImgPadding); + setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); + setGravity(Gravity.RIGHT); } @Override From e421276c3a8dd75303bba77211f30f3abf77c9ee Mon Sep 17 00:00:00 2001 From: ganeshi4u Date: Wed, 5 Feb 2020 22:53:25 -0500 Subject: [PATCH 26/51] Network Traffic: Refactor text formatting - Rework the displayed digits logic and convert them to spannable strings for better individual refinement of digits/unit - Get rid of the text size dimen as there's no need of it anymore **DU Edits** - Do to one what you do to the other. Apply the same changes to both classes, statusbar and extended statusbar. Change-Id: I7c7161460236bbc83ee530adf7c73fb9d592b3c6 --- .../SystemUI/res/values/custom_dimens.xml | 4 - .../statusbar/policy/NetworkTraffic.java | 125 ++++++++++++------ .../statusbar/policy/NetworkTrafficSB.java | 100 +++++++++----- 3 files changed, 152 insertions(+), 77 deletions(-) diff --git a/packages/SystemUI/res/values/custom_dimens.xml b/packages/SystemUI/res/values/custom_dimens.xml index 45e0115553f..6c878eb3a55 100644 --- a/packages/SystemUI/res/values/custom_dimens.xml +++ b/packages/SystemUI/res/values/custom_dimens.xml @@ -107,8 +107,4 @@ 20dp - - 13dp - 8dp - 2dp diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index ee1d9ca5c6e..743e95f0189 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -11,6 +11,9 @@ import android.database.ContentObserver; import android.graphics.drawable.Drawable; import android.graphics.PorterDuff.Mode; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.view.Gravity; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.TrafficStats; @@ -19,6 +22,10 @@ import android.os.Message; import android.os.SystemClock; import android.provider.Settings; +import android.text.Spanned; +import android.text.SpannableString; +import android.text.style.RelativeSizeSpan; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; @@ -38,21 +45,13 @@ public class NetworkTraffic extends TextView { private static final int KB = 1024; private static final int MB = KB * KB; private static final int GB = MB * KB; - private static final String symbol = "B/s"; - - private static DecimalFormat decimalFormat = new DecimalFormat("##0.#"); - static { - decimalFormat.setMaximumIntegerDigits(3); - decimalFormat.setMaximumFractionDigits(1); - } + private static final String symbol = "/s"; private boolean mIsEnabled; private boolean mAttached; private long totalRxBytes; private long totalTxBytes; private long lastUpdateTime; - private int txtSize; - private int txtImgPadding; private int mAutoHideThreshold; private int mTintColor; @@ -82,17 +81,28 @@ public void handleMessage(Message msg) { if (shouldHide(rxData, txData, timeDelta)) { setText(""); setVisibility(View.GONE); + } else if (shouldShowUpload(rxData, txData, timeDelta)) { + // Show information for uplink if it's called for + CharSequence output = formatOutput(timeDelta, txData, symbol); + + // Update view if there's anything new to show + if (output != getText()) { + setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); + setGravity(Gravity.CENTER); + setMaxLines(2); + setLineSpacing(0.75f, 0.75f); + setText(output); + } } else { - // Get information for uplink ready so the line return can be added - String output = formatOutput(timeDelta, txData, symbol); - // Ensure text size is where it needs to be - output += "\n"; // Add information for downlink if it's called for - output += formatOutput(timeDelta, rxData, symbol); + CharSequence output = formatOutput(timeDelta, rxData, symbol); // Update view if there's anything new to show - if (!output.contentEquals(getText())) { - setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); + if (output != getText()) { + setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); + setGravity(Gravity.CENTER); + setMaxLines(2); + setLineSpacing(0.75f, 0.75f); setText(output); } setVisibility(View.VISIBLE); @@ -105,25 +115,70 @@ public void handleMessage(Message msg) { mTrafficHandler.postDelayed(mRunnable, INTERVAL); } - private String formatOutput(long timeDelta, long data, String symbol) { + private CharSequence formatOutput(long timeDelta, long data, String symbol) { long speed = (long)(data / (timeDelta / 1000F)); - if (speed < KB) { - return decimalFormat.format(speed) + symbol; - } else if (speed < MB) { - return decimalFormat.format(speed / (float)KB) + 'k' + symbol; - } else if (speed < GB) { - return decimalFormat.format(speed / (float)MB) + 'M' + symbol; + + return formatDecimal(speed); + } + + private CharSequence formatDecimal(long speed) { + DecimalFormat mDecimalFormat; + String mUnit; + String formatSpeed; + SpannableString spanUnitString; + SpannableString spanSpeedString; + + if (speed >= GB) { + mUnit = "GB"; + mDecimalFormat = new DecimalFormat("0.00"); + formatSpeed = mDecimalFormat.format(speed / (float)GB); + } else if (speed >= 100 * MB) { + mDecimalFormat = new DecimalFormat("000"); + mUnit = "MB"; + formatSpeed = mDecimalFormat.format(speed / (float)MB); + } else if (speed >= 10 * MB) { + mDecimalFormat = new DecimalFormat("00.0"); + mUnit = "MB"; + formatSpeed = mDecimalFormat.format(speed / (float)MB); + } else if (speed >= MB) { + mDecimalFormat = new DecimalFormat("0.00"); + mUnit = "MB"; + formatSpeed = mDecimalFormat.format(speed / (float)MB); + } else if (speed >= 100 * KB) { + mDecimalFormat = new DecimalFormat("000"); + mUnit = "KB"; + formatSpeed = mDecimalFormat.format(speed / (float)KB); + } else if (speed >= 10 * KB) { + mDecimalFormat = new DecimalFormat("00.0"); + mUnit = "KB"; + formatSpeed = mDecimalFormat.format(speed / (float)MB); + } else { + mDecimalFormat = new DecimalFormat("0.00"); + mUnit = "KB"; + formatSpeed = mDecimalFormat.format(speed / (float)KB); } - return decimalFormat.format(speed / (float)GB) + 'G' + symbol; + spanSpeedString = new SpannableString(formatSpeed); + spanSpeedString.setSpan(new RelativeSizeSpan(0.75f), 0, (formatSpeed).length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + + spanUnitString = new SpannableString(mUnit + symbol); + spanUnitString.setSpan(new RelativeSizeSpan(0.70f), 0, (mUnit + symbol).length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + return TextUtils.concat(spanSpeedString, "\n", spanUnitString); } private boolean shouldHide(long rxData, long txData, long timeDelta) { - long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; long speedRxKB = (long)(rxData / (timeDelta / 1000f)) / KB; + long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; return !getConnectAvailable() || (speedRxKB < mAutoHideThreshold && speedTxKB < mAutoHideThreshold); } + + private boolean shouldShowUpload(long rxData, long txData, long timeDelta) { + long speedRxKB = (long)(rxData / (timeDelta / 1000f)) / KB; + long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; + + return (speedTxKB > speedRxKB); + } }; private Runnable mRunnable = new Runnable() { @@ -178,8 +233,6 @@ public NetworkTraffic(Context context, AttributeSet attrs) { public NetworkTraffic(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); final Resources resources = getResources(); - txtSize = resources.getDimensionPixelSize(R.dimen.net_traffic_multi_text_size); - txtImgPadding = resources.getDimensionPixelSize(R.dimen.net_traffic_txt_img_padding); mTintColor = resources.getColor(android.R.color.white); Handler mHandler = new Handler(); SettingsObserver settingsObserver = new SettingsObserver(mHandler); @@ -265,16 +318,6 @@ private void clearHandlerCallbacks() { private void updateTrafficDrawable() { int intTrafficDrawable; if (mIsEnabled) { - intTrafficDrawable = R.drawable.stat_sys_network_traffic_updown; - } else { - intTrafficDrawable = 0; - } - if (intTrafficDrawable != 0) { - Drawable d = getContext().getDrawable(intTrafficDrawable); - d.setColorFilter(mTintColor, Mode.SRC_ATOP); - setCompoundDrawablePadding(txtImgPadding); - setCompoundDrawablesWithIntrinsicBounds(null, null, d, null); - } else { setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); } setTextColor(mTintColor); @@ -282,9 +325,9 @@ private void updateTrafficDrawable() { public void onDensityOrFontScaleChanged() { final Resources resources = getResources(); - txtSize = resources.getDimensionPixelSize(R.dimen.net_traffic_multi_text_size); - txtImgPadding = resources.getDimensionPixelSize(R.dimen.net_traffic_multi_text_size); - setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); - setCompoundDrawablePadding(txtImgPadding); + setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); + setGravity(Gravity.CENTER); + setMaxLines(2); + setLineSpacing(0.75f, 0.75f); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java index 31ff00adfd4..c15f31f12d6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java @@ -22,12 +22,16 @@ import android.os.Message; import android.os.SystemClock; import android.provider.Settings; +import android.text.Spanned; +import android.text.SpannableString; +import android.text.style.RelativeSizeSpan; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import android.widget.TextView; -import com.android.internal.util.arrow.ArrowUtils; +import com.android.internal.util.custom.CustomUtils; import com.android.systemui.Dependency; import com.android.systemui.plugins.DarkIconDispatcher; @@ -48,18 +52,11 @@ public class NetworkTrafficSB extends TextView implements DarkReceiver { private static final int GB = MB * KB; private static final String symbol = "/s"; - private static DecimalFormat decimalFormat = new DecimalFormat("##0.#"); - static { - decimalFormat.setMaximumIntegerDigits(3); - decimalFormat.setMaximumFractionDigits(1); - } - private boolean mIsEnabled; private boolean mAttached; private long totalRxBytes; private long totalTxBytes; private long lastUpdateTime; - private int txtSize; private int mAutoHideThreshold; private int mTintColor; @@ -93,27 +90,29 @@ public void handleMessage(Message msg) { setVisibility(View.GONE); } else if (shouldShowUpload(rxData, txData, timeDelta)) { // Show information for uplink if it's called for - String output = formatOutput(timeDelta, txData, symbol); + CharSequence output = formatOutput(timeDelta, txData, symbol); // Update view if there's anything new to show - if (!output.contentEquals(getText())) { - setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); - setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); - setGravity(Gravity.RIGHT); + if (output != getText()) { + setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); + setGravity(Gravity.CENTER); + setMaxLines(2); + setLineSpacing(0.75f, 0.75f); setText(output); } } else { // Add information for downlink if it's called for - String output = formatOutput(timeDelta, rxData, symbol); + CharSequence output = formatOutput(timeDelta, rxData, symbol); // Update view if there's anything new to show - if (!output.contentEquals(getText())) { - setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); - setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); - setGravity(Gravity.RIGHT); + if (output != getText()) { + setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); + setGravity(Gravity.CENTER); + setMaxLines(2); + setLineSpacing(0.75f, 0.75f); setText(output); } - setVisibility(ArrowUtils.hasNotch(mContext) ? View.GONE : View.VISIBLE); + setVisibility(CustomUtils.hasNotch(mContext) ? View.GONE : View.VISIBLE); } // Post delayed message to refresh in ~1000ms @@ -123,16 +122,54 @@ public void handleMessage(Message msg) { mTrafficHandler.postDelayed(mRunnable, INTERVAL); } - private String formatOutput(long timeDelta, long data, String symbol) { + private CharSequence formatOutput(long timeDelta, long data, String symbol) { long speed = (long)(data / (timeDelta / 1000F)); - if (speed < KB) { - return decimalFormat.format(speed / (float)KB) + 'K' + symbol; - } else if (speed < MB) { - return decimalFormat.format(speed / (float)KB) + 'K' + symbol; - } else if (speed < GB) { - return decimalFormat.format(speed / (float)MB) + 'M' + symbol; + + return formatDecimal(speed); + } + + private CharSequence formatDecimal(long speed) { + DecimalFormat mDecimalFormat; + String mUnit; + String formatSpeed; + SpannableString spanUnitString; + SpannableString spanSpeedString; + + if (speed >= GB) { + mUnit = "GB"; + mDecimalFormat = new DecimalFormat("0.00"); + formatSpeed = mDecimalFormat.format(speed / (float)GB); + } else if (speed >= 100 * MB) { + mDecimalFormat = new DecimalFormat("000"); + mUnit = "MB"; + formatSpeed = mDecimalFormat.format(speed / (float)MB); + } else if (speed >= 10 * MB) { + mDecimalFormat = new DecimalFormat("00.0"); + mUnit = "MB"; + formatSpeed = mDecimalFormat.format(speed / (float)MB); + } else if (speed >= MB) { + mDecimalFormat = new DecimalFormat("0.00"); + mUnit = "MB"; + formatSpeed = mDecimalFormat.format(speed / (float)MB); + } else if (speed >= 100 * KB) { + mDecimalFormat = new DecimalFormat("000"); + mUnit = "KB"; + formatSpeed = mDecimalFormat.format(speed / (float)KB); + } else if (speed >= 10 * KB) { + mDecimalFormat = new DecimalFormat("00.0"); + mUnit = "KB"; + formatSpeed = mDecimalFormat.format(speed / (float)MB); + } else { + mDecimalFormat = new DecimalFormat("0.00"); + mUnit = "KB"; + formatSpeed = mDecimalFormat.format(speed / (float)KB); } - return decimalFormat.format(speed / (float)GB) + 'G' + symbol; + spanSpeedString = new SpannableString(formatSpeed); + spanSpeedString.setSpan(new RelativeSizeSpan(0.75f), 0, (formatSpeed).length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + + spanUnitString = new SpannableString(mUnit + symbol); + spanUnitString.setSpan(new RelativeSizeSpan(0.70f), 0, (mUnit + symbol).length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + return TextUtils.concat(spanSpeedString, "\n", spanUnitString); } private boolean shouldHide(long rxData, long txData, long timeDelta) { @@ -203,7 +240,6 @@ public NetworkTrafficSB(Context context, AttributeSet attrs) { public NetworkTrafficSB(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); final Resources resources = getResources(); - txtSize = resources.getDimensionPixelSize(R.dimen.net_traffic_sb_multi_text_size); mTintColor = resources.getColor(android.R.color.white); Handler mHandler = new Handler(); SettingsObserver settingsObserver = new SettingsObserver(mHandler); @@ -303,10 +339,10 @@ private void updateTrafficDrawable() { public void onDensityOrFontScaleChanged() { final Resources resources = getResources(); - txtSize = resources.getDimensionPixelSize(R.dimen.net_traffic_sb_multi_text_size); - setTextSize(TypedValue.COMPLEX_UNIT_PX, (float)txtSize); - setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); - setGravity(Gravity.RIGHT); + setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); + setGravity(Gravity.CENTER); + setMaxLines(2); + setLineSpacing(0.75f, 0.75f); } @Override From c8ac0cf41000c2ab22faf5c03779d69b295c3ea9 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 5 Feb 2020 23:05:33 -0500 Subject: [PATCH 27/51] Network Traffic: Adjust size/text style for extended statusbar Change-Id: I851dac6279e0b4a60b1697ce1bd6f85fc3e248b9 --- .../statusbar/policy/NetworkTraffic.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index 743e95f0189..b19a7c986cb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -87,10 +87,10 @@ public void handleMessage(Message msg) { // Update view if there's anything new to show if (output != getText()) { - setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); + setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); setGravity(Gravity.CENTER); setMaxLines(2); - setLineSpacing(0.75f, 0.75f); + setLineSpacing(0.90f, 0.90f); setText(output); } } else { @@ -99,10 +99,10 @@ public void handleMessage(Message msg) { // Update view if there's anything new to show if (output != getText()) { - setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); + setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); setGravity(Gravity.CENTER); setMaxLines(2); - setLineSpacing(0.75f, 0.75f); + setLineSpacing(0.90f, 0.90f); setText(output); } setVisibility(View.VISIBLE); @@ -158,10 +158,10 @@ private CharSequence formatDecimal(long speed) { formatSpeed = mDecimalFormat.format(speed / (float)KB); } spanSpeedString = new SpannableString(formatSpeed); - spanSpeedString.setSpan(new RelativeSizeSpan(0.75f), 0, (formatSpeed).length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + spanSpeedString.setSpan(new RelativeSizeSpan(0.90f), 0, (formatSpeed).length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); spanUnitString = new SpannableString(mUnit + symbol); - spanUnitString.setSpan(new RelativeSizeSpan(0.70f), 0, (mUnit + symbol).length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + spanUnitString.setSpan(new RelativeSizeSpan(0.80f), 0, (mUnit + symbol).length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); return TextUtils.concat(spanSpeedString, "\n", spanUnitString); } @@ -325,9 +325,9 @@ private void updateTrafficDrawable() { public void onDensityOrFontScaleChanged() { final Resources resources = getResources(); - setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); + setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); setGravity(Gravity.CENTER); setMaxLines(2); - setLineSpacing(0.75f, 0.75f); + setLineSpacing(0.90f, 0.90f); } } From feb67f10ac8a7915d5fa1407d4b32147bdb3f884 Mon Sep 17 00:00:00 2001 From: ezio84 Date: Sun, 9 Feb 2020 10:24:36 +0100 Subject: [PATCH 28/51] Traffic indicators: code cleanup and improvements also don't continuosly check if device has notch but do it once Change-Id: I1a97dcd6cb932d32f6bffa518a66a47a209c604e --- .../statusbar/policy/NetworkTraffic.java | 187 ++++++----- .../statusbar/policy/NetworkTrafficSB.java | 308 +----------------- 2 files changed, 116 insertions(+), 379 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index b19a7c986cb..0e16cb9828a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -47,13 +47,15 @@ public class NetworkTraffic extends TextView { private static final int GB = MB * KB; private static final String symbol = "/s"; - private boolean mIsEnabled; + protected boolean mIsEnabled; private boolean mAttached; private long totalRxBytes; private long totalTxBytes; private long lastUpdateTime; private int mAutoHideThreshold; - private int mTintColor; + protected int mTintColor; + + private boolean mScreenOn = true; private Handler mTrafficHandler = new Handler() { @Override @@ -87,10 +89,9 @@ public void handleMessage(Message msg) { // Update view if there's anything new to show if (output != getText()) { - setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); setGravity(Gravity.CENTER); setMaxLines(2); - setLineSpacing(0.90f, 0.90f); + setSpacingAndFonts(); setText(output); } } else { @@ -99,10 +100,9 @@ public void handleMessage(Message msg) { // Update view if there's anything new to show if (output != getText()) { - setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); setGravity(Gravity.CENTER); setMaxLines(2); - setLineSpacing(0.90f, 0.90f); + setSpacingAndFonts(); setText(output); } setVisibility(View.VISIBLE); @@ -122,97 +122,67 @@ private CharSequence formatOutput(long timeDelta, long data, String symbol) { } private CharSequence formatDecimal(long speed) { - DecimalFormat mDecimalFormat; - String mUnit; + DecimalFormat decimalFormat; + String unit; String formatSpeed; SpannableString spanUnitString; SpannableString spanSpeedString; if (speed >= GB) { - mUnit = "GB"; - mDecimalFormat = new DecimalFormat("0.00"); - formatSpeed = mDecimalFormat.format(speed / (float)GB); + unit = "GB"; + decimalFormat = new DecimalFormat("0.00"); + formatSpeed = decimalFormat.format(speed / (float)GB); } else if (speed >= 100 * MB) { - mDecimalFormat = new DecimalFormat("000"); - mUnit = "MB"; - formatSpeed = mDecimalFormat.format(speed / (float)MB); + decimalFormat = new DecimalFormat("000"); + unit = "MB"; + formatSpeed = decimalFormat.format(speed / (float)MB); } else if (speed >= 10 * MB) { - mDecimalFormat = new DecimalFormat("00.0"); - mUnit = "MB"; - formatSpeed = mDecimalFormat.format(speed / (float)MB); + decimalFormat = new DecimalFormat("00.0"); + unit = "MB"; + formatSpeed = decimalFormat.format(speed / (float)MB); } else if (speed >= MB) { - mDecimalFormat = new DecimalFormat("0.00"); - mUnit = "MB"; - formatSpeed = mDecimalFormat.format(speed / (float)MB); + decimalFormat = new DecimalFormat("0.00"); + unit = "MB"; + formatSpeed = decimalFormat.format(speed / (float)MB); } else if (speed >= 100 * KB) { - mDecimalFormat = new DecimalFormat("000"); - mUnit = "KB"; - formatSpeed = mDecimalFormat.format(speed / (float)KB); + decimalFormat = new DecimalFormat("000"); + unit = "KB"; + formatSpeed = decimalFormat.format(speed / (float)KB); } else if (speed >= 10 * KB) { - mDecimalFormat = new DecimalFormat("00.0"); - mUnit = "KB"; - formatSpeed = mDecimalFormat.format(speed / (float)MB); + decimalFormat = new DecimalFormat("00.0"); + unit = "KB"; + formatSpeed = decimalFormat.format(speed / (float)MB); } else { - mDecimalFormat = new DecimalFormat("0.00"); - mUnit = "KB"; - formatSpeed = mDecimalFormat.format(speed / (float)KB); + decimalFormat = new DecimalFormat("0.00"); + unit = "KB"; + formatSpeed = decimalFormat.format(speed / (float)KB); } spanSpeedString = new SpannableString(formatSpeed); - spanSpeedString.setSpan(new RelativeSizeSpan(0.90f), 0, (formatSpeed).length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + spanSpeedString.setSpan(getSpeedRelativeSizeSpan(), 0, (formatSpeed).length(), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); - spanUnitString = new SpannableString(mUnit + symbol); - spanUnitString.setSpan(new RelativeSizeSpan(0.80f), 0, (mUnit + symbol).length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + spanUnitString = new SpannableString(unit + symbol); + spanUnitString.setSpan(getUnitRelativeSizeSpan(), 0, (unit + symbol).length(), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); return TextUtils.concat(spanSpeedString, "\n", spanUnitString); } private boolean shouldHide(long rxData, long txData, long timeDelta) { long speedRxKB = (long)(rxData / (timeDelta / 1000f)) / KB; - long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; + long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; return !getConnectAvailable() || (speedRxKB < mAutoHideThreshold && speedTxKB < mAutoHideThreshold); } - private boolean shouldShowUpload(long rxData, long txData, long timeDelta) { - long speedRxKB = (long)(rxData / (timeDelta / 1000f)) / KB; - long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; - - return (speedTxKB > speedRxKB); - } - }; + private boolean shouldShowUpload(long rxData, long txData, long timeDelta) { + long speedRxKB = (long)(rxData / (timeDelta / 1000f)) / KB; + long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; - private Runnable mRunnable = new Runnable() { - @Override - public void run() { - mTrafficHandler.sendEmptyMessage(0); + return (speedTxKB > speedRxKB); } }; - class SettingsObserver extends ContentObserver { - SettingsObserver(Handler handler) { - super(handler); - } - - void observe() { - ContentResolver resolver = mContext.getContentResolver(); - resolver.registerContentObserver(Settings.System - .getUriFor(Settings.System.NETWORK_TRAFFIC_STATE), false, - this, UserHandle.USER_ALL); - resolver.registerContentObserver(Settings.System - .getUriFor(Settings.System.NETWORK_TRAFFIC_AUTOHIDE_THRESHOLD), false, - this, UserHandle.USER_ALL); - } - - /* - * @hide - */ - @Override - public void onChange(boolean selfChange) { - setMode(); - updateSettings(); - } - } - /* * @hide */ @@ -234,11 +204,11 @@ public NetworkTraffic(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); final Resources resources = getResources(); mTintColor = resources.getColor(android.R.color.white); + setMode(); Handler mHandler = new Handler(); SettingsObserver settingsObserver = new SettingsObserver(mHandler); settingsObserver.observe(); - setMode(); - updateSettings(); + update(); } @Override @@ -252,7 +222,7 @@ protected void onAttachedToWindow() { filter.addAction(Intent.ACTION_SCREEN_ON); mContext.registerReceiver(mIntentReceiver, filter, null, getHandler()); } - updateSettings(); + update(); } @Override @@ -264,14 +234,58 @@ protected void onDetachedFromWindow() { } } + protected RelativeSizeSpan getSpeedRelativeSizeSpan() { + return new RelativeSizeSpan(0.90f); + } + + protected RelativeSizeSpan getUnitRelativeSizeSpan() { + return new RelativeSizeSpan(0.80f); + } + + private Runnable mRunnable = new Runnable() { + @Override + public void run() { + mTrafficHandler.sendEmptyMessage(0); + } + }; + + class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + void observe() { + ContentResolver resolver = mContext.getContentResolver(); + resolver.registerContentObserver(Settings.System + .getUriFor(Settings.System.NETWORK_TRAFFIC_STATE), false, + this, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.System + .getUriFor(Settings.System.NETWORK_TRAFFIC_AUTOHIDE_THRESHOLD), false, + this, UserHandle.USER_ALL); + } + + /* + * @hide + */ + @Override + public void onChange(boolean selfChange) { + setMode(); + update(); + } + } + private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (action != null && action.equals(ConnectivityManager.CONNECTIVITY_ACTION) - || action.equals(Intent.ACTION_SCREEN_ON)) { - updateSettings(); - } else if (action != null && action.equals(Intent.ACTION_SCREEN_OFF)) { + if (action == null) return; + if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) && mScreenOn) { + update(); + } else if (action.equals(Intent.ACTION_SCREEN_ON)) { + mScreenOn = true; + update(); + } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { + mScreenOn = false; clearHandlerCallbacks(); } } @@ -284,7 +298,7 @@ private boolean getConnectAvailable() { return network != null; } - private void updateSettings() { + private void update() { if (mIsEnabled) { if (mAttached) { totalRxBytes = TrafficStats.getTotalRxBytes(); @@ -299,7 +313,7 @@ private void updateSettings() { setVisibility(View.GONE); } - private void setMode() { + protected void setMode() { ContentResolver resolver = mContext.getContentResolver(); mIsEnabled = Settings.System.getIntForUser(resolver, Settings.System.NETWORK_TRAFFIC_STATE, 0, @@ -315,19 +329,18 @@ private void clearHandlerCallbacks() { mTrafficHandler.removeMessages(1); } - private void updateTrafficDrawable() { - int intTrafficDrawable; - if (mIsEnabled) { - setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); - } + protected void updateTrafficDrawable() { + setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); setTextColor(mTintColor); } - public void onDensityOrFontScaleChanged() { - final Resources resources = getResources(); + protected void setSpacingAndFonts() { setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); - setGravity(Gravity.CENTER); - setMaxLines(2); setLineSpacing(0.90f, 0.90f); } + + public void onDensityOrFontScaleChanged() { + setSpacingAndFonts(); + update(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java index c15f31f12d6..0b360df1e91 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java @@ -1,225 +1,18 @@ package com.android.systemui.statusbar.policy; -import java.text.DecimalFormat; - -import android.content.BroadcastReceiver; -import android.content.ContentResolver; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.Resources; -import android.database.ContentObserver; -import android.graphics.drawable.Drawable; -import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.graphics.Typeface; -import android.view.Gravity; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.net.TrafficStats; -import android.os.Handler; -import android.os.UserHandle; -import android.os.Message; -import android.os.SystemClock; -import android.provider.Settings; -import android.text.Spanned; -import android.text.SpannableString; import android.text.style.RelativeSizeSpan; -import android.text.TextUtils; import android.util.AttributeSet; -import android.util.TypedValue; -import android.view.View; -import android.widget.TextView; import com.android.internal.util.custom.CustomUtils; import com.android.systemui.Dependency; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; -import com.android.systemui.R; - -/* -* -* Seeing how an Integer object in java requires at least 16 Bytes, it seemed awfully wasteful -* to only use it for a single boolean. 32-bits is plenty of room for what we need it to do. -* -*/ -public class NetworkTrafficSB extends TextView implements DarkReceiver { - - private static final int INTERVAL = 1500; //ms - private static final int KB = 1024; - private static final int MB = KB * KB; - private static final int GB = MB * KB; - private static final String symbol = "/s"; - - private boolean mIsEnabled; - private boolean mAttached; - private long totalRxBytes; - private long totalTxBytes; - private long lastUpdateTime; - private int mAutoHideThreshold; - private int mTintColor; - - private boolean mScreenOn = true; - - private Handler mTrafficHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - long timeDelta = SystemClock.elapsedRealtime() - lastUpdateTime; - - if (timeDelta < INTERVAL * .95) { - if (msg.what != 1) { - // we just updated the view, nothing further to do - return; - } - if (timeDelta < 1) { - // Can't div by 0 so make sure the value displayed is minimal - timeDelta = Long.MAX_VALUE; - } - } - lastUpdateTime = SystemClock.elapsedRealtime(); - - // Calculate the data rate from the change in total bytes and time - long newTotalRxBytes = TrafficStats.getTotalRxBytes(); - long newTotalTxBytes = TrafficStats.getTotalTxBytes(); - long rxData = newTotalRxBytes - totalRxBytes; - long txData = newTotalTxBytes - totalTxBytes; - - if (shouldHide(rxData, txData, timeDelta)) { - setText(""); - setVisibility(View.GONE); - } else if (shouldShowUpload(rxData, txData, timeDelta)) { - // Show information for uplink if it's called for - CharSequence output = formatOutput(timeDelta, txData, symbol); - - // Update view if there's anything new to show - if (output != getText()) { - setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); - setGravity(Gravity.CENTER); - setMaxLines(2); - setLineSpacing(0.75f, 0.75f); - setText(output); - } - } else { - // Add information for downlink if it's called for - CharSequence output = formatOutput(timeDelta, rxData, symbol); - - // Update view if there's anything new to show - if (output != getText()) { - setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); - setGravity(Gravity.CENTER); - setMaxLines(2); - setLineSpacing(0.75f, 0.75f); - setText(output); - } - setVisibility(CustomUtils.hasNotch(mContext) ? View.GONE : View.VISIBLE); - } - - // Post delayed message to refresh in ~1000ms - totalRxBytes = newTotalRxBytes; - totalTxBytes = newTotalTxBytes; - clearHandlerCallbacks(); - mTrafficHandler.postDelayed(mRunnable, INTERVAL); - } - - private CharSequence formatOutput(long timeDelta, long data, String symbol) { - long speed = (long)(data / (timeDelta / 1000F)); - - return formatDecimal(speed); - } - - private CharSequence formatDecimal(long speed) { - DecimalFormat mDecimalFormat; - String mUnit; - String formatSpeed; - SpannableString spanUnitString; - SpannableString spanSpeedString; - - if (speed >= GB) { - mUnit = "GB"; - mDecimalFormat = new DecimalFormat("0.00"); - formatSpeed = mDecimalFormat.format(speed / (float)GB); - } else if (speed >= 100 * MB) { - mDecimalFormat = new DecimalFormat("000"); - mUnit = "MB"; - formatSpeed = mDecimalFormat.format(speed / (float)MB); - } else if (speed >= 10 * MB) { - mDecimalFormat = new DecimalFormat("00.0"); - mUnit = "MB"; - formatSpeed = mDecimalFormat.format(speed / (float)MB); - } else if (speed >= MB) { - mDecimalFormat = new DecimalFormat("0.00"); - mUnit = "MB"; - formatSpeed = mDecimalFormat.format(speed / (float)MB); - } else if (speed >= 100 * KB) { - mDecimalFormat = new DecimalFormat("000"); - mUnit = "KB"; - formatSpeed = mDecimalFormat.format(speed / (float)KB); - } else if (speed >= 10 * KB) { - mDecimalFormat = new DecimalFormat("00.0"); - mUnit = "KB"; - formatSpeed = mDecimalFormat.format(speed / (float)MB); - } else { - mDecimalFormat = new DecimalFormat("0.00"); - mUnit = "KB"; - formatSpeed = mDecimalFormat.format(speed / (float)KB); - } - spanSpeedString = new SpannableString(formatSpeed); - spanSpeedString.setSpan(new RelativeSizeSpan(0.75f), 0, (formatSpeed).length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); - - spanUnitString = new SpannableString(mUnit + symbol); - spanUnitString.setSpan(new RelativeSizeSpan(0.70f), 0, (mUnit + symbol).length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); - return TextUtils.concat(spanSpeedString, "\n", spanUnitString); - } - - private boolean shouldHide(long rxData, long txData, long timeDelta) { - long speedRxKB = (long)(rxData / (timeDelta / 1000f)) / KB; - long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; - return !getConnectAvailable() || - (speedRxKB < mAutoHideThreshold && - speedTxKB < mAutoHideThreshold); - } - - private boolean shouldShowUpload(long rxData, long txData, long timeDelta) { - long speedRxKB = (long)(rxData / (timeDelta / 1000f)) / KB; - long speedTxKB = (long)(txData / (timeDelta / 1000f)) / KB; - - return (speedTxKB > speedRxKB); - } - }; - - private Runnable mRunnable = new Runnable() { - @Override - public void run() { - mTrafficHandler.sendEmptyMessage(0); - } - }; - - class SettingsObserver extends ContentObserver { - SettingsObserver(Handler handler) { - super(handler); - } - - void observe() { - ContentResolver resolver = mContext.getContentResolver(); - resolver.registerContentObserver(Settings.System - .getUriFor(Settings.System.NETWORK_TRAFFIC_STATE), false, - this, UserHandle.USER_ALL); - resolver.registerContentObserver(Settings.System - .getUriFor(Settings.System.NETWORK_TRAFFIC_AUTOHIDE_THRESHOLD), false, - this, UserHandle.USER_ALL); - } - - /* - * @hide - */ - @Override - public void onChange(boolean selfChange) { - setMode(); - updateSettings(); - } - } +public class NetworkTrafficSB extends NetworkTraffic implements DarkReceiver { /* * @hide */ @@ -239,114 +32,45 @@ public NetworkTrafficSB(Context context, AttributeSet attrs) { */ public NetworkTrafficSB(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - final Resources resources = getResources(); - mTintColor = resources.getColor(android.R.color.white); - Handler mHandler = new Handler(); - SettingsObserver settingsObserver = new SettingsObserver(mHandler); - settingsObserver.observe(); - setMode(); - updateSettings(); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - if (!mAttached) { - mAttached = true; - IntentFilter filter = new IntentFilter(); - filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - filter.addAction(Intent.ACTION_SCREEN_OFF); - filter.addAction(Intent.ACTION_SCREEN_ON); - mContext.registerReceiver(mIntentReceiver, filter, null, getHandler()); - } Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this); - updateSettings(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - if (mAttached) { - mContext.unregisterReceiver(mIntentReceiver); - mAttached = false; - } Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this); } - private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action == null) return; - - if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) && mScreenOn) { - updateSettings(); - } else if (action.equals(Intent.ACTION_SCREEN_ON)) { - mScreenOn = true; - updateSettings(); - } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { - mScreenOn = false; - clearHandlerCallbacks(); - } - } - }; - - private boolean getConnectAvailable() { - ConnectivityManager connManager = - (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo network = (connManager != null) ? connManager.getActiveNetworkInfo() : null; - return network != null; - } - - private void updateSettings() { - if (mIsEnabled) { - if (mAttached) { - totalRxBytes = TrafficStats.getTotalRxBytes(); - lastUpdateTime = SystemClock.elapsedRealtime(); - mTrafficHandler.sendEmptyMessage(1); - } - updateTrafficDrawable(); - return; - } else { - clearHandlerCallbacks(); - } - setVisibility(View.GONE); - } - - private void setMode() { - ContentResolver resolver = mContext.getContentResolver(); - mIsEnabled = Settings.System.getIntForUser(resolver, - Settings.System.NETWORK_TRAFFIC_STATE, 0, - UserHandle.USER_CURRENT) == 1; - mAutoHideThreshold = Settings.System.getIntForUser(resolver, - Settings.System.NETWORK_TRAFFIC_AUTOHIDE_THRESHOLD, 0, - UserHandle.USER_CURRENT); + @Override + protected void setMode() { + super.setMode(); + mIsEnabled = mIsEnabled && !ArrowUtils.hasNotch(mContext); } - private void clearHandlerCallbacks() { - mTrafficHandler.removeCallbacks(mRunnable); - mTrafficHandler.removeMessages(0); - mTrafficHandler.removeMessages(1); + @Override + protected void setSpacingAndFonts() { + setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); + setLineSpacing(0.75f, 0.75f); } - private void updateTrafficDrawable() { - int intTrafficDrawable; - if (mIsEnabled) { - setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); - } - setTextColor(mTintColor); + @Override + protected RelativeSizeSpan getSpeedRelativeSizeSpan() { + return new RelativeSizeSpan(0.75f); } - public void onDensityOrFontScaleChanged() { - final Resources resources = getResources(); - setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); - setGravity(Gravity.CENTER); - setMaxLines(2); - setLineSpacing(0.75f, 0.75f); + @Override + protected RelativeSizeSpan getUnitRelativeSizeSpan() { + return new RelativeSizeSpan(0.7f); } @Override public void onDarkChanged(Rect area, float darkIntensity, int tint) { + if (!mIsEnabled) return; mTintColor = DarkIconDispatcher.getTint(area, this, tint); setTextColor(mTintColor); updateTrafficDrawable(); From 32b4caec0b40d8c5af0c8b8fd2127d8fd4aee426 Mon Sep 17 00:00:00 2001 From: ezio84 Date: Sun, 9 Feb 2020 15:21:33 +0100 Subject: [PATCH 29/51] Traffic indicators: use smaller and bold fonts in expanded statusbar Change-Id: I7d9dd2fe7850ec6f27707022fc8e4fd3cf85dfd1 --- .../android/systemui/statusbar/policy/NetworkTraffic.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index 0e16cb9828a..ccbb67c4dcd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -235,11 +235,11 @@ protected void onDetachedFromWindow() { } protected RelativeSizeSpan getSpeedRelativeSizeSpan() { - return new RelativeSizeSpan(0.90f); + return new RelativeSizeSpan(0.80f); } protected RelativeSizeSpan getUnitRelativeSizeSpan() { - return new RelativeSizeSpan(0.80f); + return new RelativeSizeSpan(0.75f); } private Runnable mRunnable = new Runnable() { @@ -335,8 +335,8 @@ protected void updateTrafficDrawable() { } protected void setSpacingAndFonts() { - setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL)); - setLineSpacing(0.90f, 0.90f); + setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); + setLineSpacing(0.80f, 0.80f); } public void onDensityOrFontScaleChanged() { From 535291baa31466bde0a60927cf43f1fc1b1b1070 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Tue, 11 Feb 2020 18:45:51 -0500 Subject: [PATCH 30/51] Traffic indicators: add properly to statusbar icons Make it behave fine on devices that don't have much status bar space (e.g. because of a display cutout/"notch") duabc: adapt to our code Change-Id: I541e2430e2075d8dc650829d5e90039628799a15 --- packages/SystemUI/res/layout/system_icons.xml | 16 +---- .../phone/PhoneStatusBarTransitions.java | 7 +- .../phone/StatusBarIconController.java | 17 +++++ .../statusbar/phone/StatusBarIconHolder.java | 9 +++ .../statusbar/phone/StatusBarIconList.java | 9 ++- .../statusbar/policy/NetworkTraffic.java | 8 ++- .../statusbar/policy/NetworkTrafficSB.java | 64 ++++++++++++++++++- 7 files changed, 104 insertions(+), 26 deletions(-) diff --git a/packages/SystemUI/res/layout/system_icons.xml b/packages/SystemUI/res/layout/system_icons.xml index c80be5fc8c8..818d1d77177 100644 --- a/packages/SystemUI/res/layout/system_icons.xml +++ b/packages/SystemUI/res/layout/system_icons.xml @@ -21,23 +21,9 @@ android:layout_height="match_parent" android:gravity="center_vertical"> - - - - - mSlots = new ArrayList<>(); @@ -35,6 +37,9 @@ public StatusBarIconList(String[] slots) { for (int i=0; i < N; i++) { mSlots.add(new Slot(slots[i], null)); } + + // Network traffic slot + mSlots.add(0, new Slot(NetworkTrafficSB.SLOT, StatusBarIconHolder.fromNetworkTraffic())); } public int getSlotIndex(String slot) { @@ -45,8 +50,8 @@ public int getSlotIndex(String slot) { return i; } } - // Auto insert new items at the beginning. - mSlots.add(0, new Slot(slot, null)); + // Auto insert new items behind network traffic + mSlots.add(1, new Slot(slot, null)); return 0; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index ccbb67c4dcd..c4f6129a80c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -105,7 +105,7 @@ public void handleMessage(Message msg) { setSpacingAndFonts(); setText(output); } - setVisibility(View.VISIBLE); + makeVisible(); } // Post delayed message to refresh in ~1000ms @@ -183,6 +183,10 @@ private boolean shouldShowUpload(long rxData, long txData, long timeDelta) { } }; + protected void makeVisible() { + setVisibility(View.VISIBLE); + } + /* * @hide */ @@ -298,7 +302,7 @@ private boolean getConnectAvailable() { return network != null; } - private void update() { + protected void update() { if (mIsEnabled) { if (mAttached) { totalRxBytes = TrafficStats.getTotalRxBytes(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java index 0b360df1e91..331d3259ac7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java @@ -1,5 +1,9 @@ package com.android.systemui.statusbar.policy; +import static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT; +import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN; +import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON; + import android.content.Context; import android.graphics.Rect; import android.graphics.Typeface; @@ -11,8 +15,15 @@ import com.android.systemui.Dependency; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; +import com.android.systemui.statusbar.StatusIconDisplayable; + +public class NetworkTrafficSB extends NetworkTraffic implements DarkReceiver, StatusIconDisplayable { + + public static final String SLOT = "networktraffic"; + private int mVisibleState = -1; + private boolean mTrafficVisible = false; + private boolean mSystemIconVisible = true; -public class NetworkTrafficSB extends NetworkTraffic implements DarkReceiver { /* * @hide */ @@ -75,4 +86,55 @@ public void onDarkChanged(Rect area, float darkIntensity, int tint) { setTextColor(mTintColor); updateTrafficDrawable(); } + + @Override + public String getSlot() { + return SLOT; + } + + @Override + public boolean isIconVisible() { + return mIsEnabled; + } + + @Override + public int getVisibleState() { + return mVisibleState; + } + + @Override + public void setVisibleState(int state, boolean mIsEnabled) { + if (state == mVisibleState) { + return; + } + mVisibleState = state; + + switch (state) { + case STATE_ICON: + mSystemIconVisible = true; + break; + case STATE_DOT: + case STATE_HIDDEN: + default: + mSystemIconVisible = false; + break; + } + update(); + } + + @Override + protected void makeVisible() { + setVisibility(mSystemIconVisible ? View.VISIBLE : View.GONE); + } + + @Override + public void setStaticDrawableColor(int color) { + mTintColor = color; + setTextColor(mTintColor); + updateTrafficDrawable(); + } + + @Override + public void setDecorColor(int color) { + } } From 6d629f9ffd2e14124d146ef86767fa636716a58f Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 11 Feb 2020 20:42:11 -0500 Subject: [PATCH 31/51] Traffic indicators: hide in the keyguard There's no fucking reason for these traffic indicators to be showing in the keyguard. Who does that? Nobody....that's who lol Change-Id: Ie7f8cfbbf787d3096094c31daa6feff0e305a687 --- .../statusbar/policy/NetworkTrafficSB.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java index 331d3259ac7..60427942013 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java @@ -9,13 +9,16 @@ import android.graphics.Typeface; import android.text.style.RelativeSizeSpan; import android.util.AttributeSet; +import android.view.View; import com.android.internal.util.custom.CustomUtils; import com.android.systemui.Dependency; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.statusbar.StatusIconDisplayable; +import com.android.systemui.statusbar.policy.KeyguardMonitor; public class NetworkTrafficSB extends NetworkTraffic implements DarkReceiver, StatusIconDisplayable { @@ -24,6 +27,9 @@ public class NetworkTrafficSB extends NetworkTraffic implements DarkReceiver, St private boolean mTrafficVisible = false; private boolean mSystemIconVisible = true; + private final KeyguardMonitor mKeyguard; + private final KeyguardCallback mKeyguardCallback = new KeyguardCallback(); + /* * @hide */ @@ -43,17 +49,20 @@ public NetworkTrafficSB(Context context, AttributeSet attrs) { */ public NetworkTrafficSB(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + mKeyguard = Dependency.get(KeyguardMonitor.class); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + mKeyguard.addCallback(mKeyguardCallback); Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + mKeyguard.removeCallback(mKeyguardCallback); Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this); } @@ -124,7 +133,7 @@ public void setVisibleState(int state, boolean mIsEnabled) { @Override protected void makeVisible() { - setVisibility(mSystemIconVisible ? View.VISIBLE : View.GONE); + setVisibility(mSystemIconVisible && !mKeyguard.isShowing() ? View.VISIBLE : View.GONE); } @Override @@ -137,4 +146,11 @@ public void setStaticDrawableColor(int color) { @Override public void setDecorColor(int color) { } + + private final class KeyguardCallback implements KeyguardMonitor.Callback { + @Override + public void onKeyguardShowingChanged() { + update(); + } + }; } From f243241a210bb032a1ad897fbd79c678b0f5a3ac Mon Sep 17 00:00:00 2001 From: ezio84 Date: Wed, 12 Feb 2020 19:41:28 +0100 Subject: [PATCH 32/51] Traffic indicators: don't show two instances in expanded statusbar we keep the one on top right of the screen (there we have more space and in the future can add more net traffic info) Change-Id: I098c93b9dd0edd146d08fd23c8c721274b9859ec --- .../systemui/statusbar/phone/StatusBar.java | 3 ++ .../phone/StatusBarIconController.java | 16 +++++++ .../phone/StatusBarIconControllerImpl.java | 12 ++++++ .../statusbar/policy/NetworkTraffic.java | 13 ++++-- .../statusbar/policy/NetworkTrafficSB.java | 43 +++++++++++++------ 5 files changed, 70 insertions(+), 17 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index c3c442b98f6..2a3e2a0dd41 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1994,6 +1994,7 @@ public void setPanelExpanded(boolean isExpanded) { if (!isExpanded) { mRemoteInputManager.onPanelCollapsed(); } + ((StatusBarIconControllerImpl) mIconController).onPanelExpanded(isExpanded); } public ViewGroup getNotificationScrollLayout() { @@ -4125,6 +4126,8 @@ public void onStateChanged(int newState) { mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD); mPulseController.setKeyguardShowing(mState == StatusBarState.KEYGUARD); updateKeyguardState(); + + ((StatusBarIconControllerImpl) mIconController).setKeyguardShowing(mState == StatusBarState.KEYGUARD); Trace.endSection(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java index 8291fa269ae..bd630592d80 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -443,5 +443,21 @@ protected void exitDemoMode() { protected DemoStatusIcons createDemoStatusIcons() { return new DemoStatusIcons((LinearLayout) mGroup, mIconSize); } + + public void onPanelExpanded(boolean isExpanded) { + for (int i = 0; i < mGroup.getChildCount(); i++) { + if (mGroup.getChildAt(i) instanceof NetworkTrafficSB) { + ((NetworkTrafficSB)mGroup.getChildAt(i)).onPanelExpanded(isExpanded); + } + } + } + + public void setKeyguardShowing(boolean showing) { + for (int i = 0; i < mGroup.getChildCount(); i++) { + if (mGroup.getChildAt(i) instanceof NetworkTrafficSB) { + ((NetworkTrafficSB)mGroup.getChildAt(i)).setKeyguardShowing(showing); + } + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java index d0e806769f1..89c9bd56222 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java @@ -347,6 +347,18 @@ public void dispatchDemoCommand(String command, Bundle args) { } } + public void onPanelExpanded(boolean isExpanded) { + for (IconManager manager : mIconGroups) { + manager.onPanelExpanded(isExpanded); + } + } + + public void setKeyguardShowing(boolean showing) { + for (IconManager manager : mIconGroups) { + manager.setKeyguardShowing(showing); + } + } + @Override public void onDensityOrFontScaleChanged() { loadDimens(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index c4f6129a80c..8b905a15af9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -57,6 +57,8 @@ public class NetworkTraffic extends TextView { private boolean mScreenOn = true; + private ConnectivityManager mConnectivityManager; + private Handler mTrafficHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -183,6 +185,10 @@ private boolean shouldShowUpload(long rxData, long txData, long timeDelta) { } }; + protected boolean restoreViewQuickly() { + return getConnectAvailable() && mAutoHideThreshold == 0; + } + protected void makeVisible() { setVisibility(View.VISIBLE); } @@ -210,6 +216,8 @@ public NetworkTraffic(Context context, AttributeSet attrs, int defStyle) { mTintColor = resources.getColor(android.R.color.white); setMode(); Handler mHandler = new Handler(); + mConnectivityManager = + (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); SettingsObserver settingsObserver = new SettingsObserver(mHandler); settingsObserver.observe(); update(); @@ -296,9 +304,7 @@ public void onReceive(Context context, Intent intent) { }; private boolean getConnectAvailable() { - ConnectivityManager connManager = - (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo network = (connManager != null) ? connManager.getActiveNetworkInfo() : null; + NetworkInfo network = (mConnectivityManager != null) ? mConnectivityManager.getActiveNetworkInfo() : null; return network != null; } @@ -325,6 +331,7 @@ protected void setMode() { mAutoHideThreshold = Settings.System.getIntForUser(resolver, Settings.System.NETWORK_TRAFFIC_AUTOHIDE_THRESHOLD, 1, UserHandle.USER_CURRENT); + setVisibility(View.GONE); } private void clearHandlerCallbacks() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java index 60427942013..f4b4299c055 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java @@ -14,11 +14,9 @@ import com.android.internal.util.custom.CustomUtils; import com.android.systemui.Dependency; -import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.statusbar.StatusIconDisplayable; -import com.android.systemui.statusbar.policy.KeyguardMonitor; public class NetworkTrafficSB extends NetworkTraffic implements DarkReceiver, StatusIconDisplayable { @@ -26,9 +24,8 @@ public class NetworkTrafficSB extends NetworkTraffic implements DarkReceiver, St private int mVisibleState = -1; private boolean mTrafficVisible = false; private boolean mSystemIconVisible = true; - - private final KeyguardMonitor mKeyguard; - private final KeyguardCallback mKeyguardCallback = new KeyguardCallback(); + private boolean mStatusbarExpanded; + private boolean mKeyguardShowing; /* * @hide @@ -49,20 +46,17 @@ public NetworkTrafficSB(Context context, AttributeSet attrs) { */ public NetworkTrafficSB(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - mKeyguard = Dependency.get(KeyguardMonitor.class); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - mKeyguard.addCallback(mKeyguardCallback); Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - mKeyguard.removeCallback(mKeyguardCallback); Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this); } @@ -133,7 +127,9 @@ public void setVisibleState(int state, boolean mIsEnabled) { @Override protected void makeVisible() { - setVisibility(mSystemIconVisible && !mKeyguard.isShowing() ? View.VISIBLE : View.GONE); + setVisibility( + !mStatusbarExpanded && mSystemIconVisible && !mKeyguardShowing ? View.VISIBLE + : View.GONE); } @Override @@ -147,10 +143,29 @@ public void setStaticDrawableColor(int color) { public void setDecorColor(int color) { } - private final class KeyguardCallback implements KeyguardMonitor.Callback { - @Override - public void onKeyguardShowingChanged() { - update(); + public void onPanelExpanded(boolean isExpanded) { + mStatusbarExpanded = isExpanded; + if (isExpanded) { + setVisibility(View.GONE); + } + maybeRestoreVisibility(); + } + + public void setKeyguardShowing(boolean showing) { + mKeyguardShowing = showing; + if (showing) { + setVisibility(View.GONE); } - }; + maybeRestoreVisibility(); + } + + private void maybeRestoreVisibility() { + if (mIsEnabled && !mStatusbarExpanded && !mKeyguardShowing && mSystemIconVisible + && restoreViewQuickly()) { + setVisibility(View.VISIBLE); + // then let the traffic handler do its checks + update(); + } + + } } From 87b16a43bf5e66e037a9b377f596ce3e288102cb Mon Sep 17 00:00:00 2001 From: ezio84 Date: Fri, 14 Feb 2020 02:55:14 -0500 Subject: [PATCH 33/51] Traffic indicators: Prevent logspam caused by improperly calling requestLayout() Simple as that. Improperly calling requestLayout() was causing ViewRootImpl spam the living crap out of us. https://github.com/DirtyUnicorns/android_frameworks_base/blob/q10x/core/java/android/view/ViewRootImpl.java#L3178 Change-Id: Ia7f20be9e31508ab5188ceeaeb83716ab6548d02 --- .../statusbar/policy/NetworkTraffic.java | 17 +++++++++-------- .../statusbar/policy/NetworkTrafficSB.java | 16 +++++++++++----- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index 8b905a15af9..189808d0ea7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -56,7 +56,7 @@ public class NetworkTraffic extends TextView { protected int mTintColor; private boolean mScreenOn = true; - + protected boolean mVisible = true; private ConnectivityManager mConnectivityManager; private Handler mTrafficHandler = new Handler() { @@ -85,15 +85,13 @@ public void handleMessage(Message msg) { if (shouldHide(rxData, txData, timeDelta)) { setText(""); setVisibility(View.GONE); + mVisible = false; } else if (shouldShowUpload(rxData, txData, timeDelta)) { // Show information for uplink if it's called for CharSequence output = formatOutput(timeDelta, txData, symbol); // Update view if there's anything new to show if (output != getText()) { - setGravity(Gravity.CENTER); - setMaxLines(2); - setSpacingAndFonts(); setText(output); } } else { @@ -102,9 +100,6 @@ public void handleMessage(Message msg) { // Update view if there's anything new to show if (output != getText()) { - setGravity(Gravity.CENTER); - setMaxLines(2); - setSpacingAndFonts(); setText(output); } makeVisible(); @@ -191,6 +186,7 @@ protected boolean restoreViewQuickly() { protected void makeVisible() { setVisibility(View.VISIBLE); + mVisible = true; } /* @@ -315,12 +311,12 @@ protected void update() { lastUpdateTime = SystemClock.elapsedRealtime(); mTrafficHandler.sendEmptyMessage(1); } - updateTrafficDrawable(); return; } else { clearHandlerCallbacks(); } setVisibility(View.GONE); + mVisible = false; } protected void setMode() { @@ -331,7 +327,12 @@ protected void setMode() { mAutoHideThreshold = Settings.System.getIntForUser(resolver, Settings.System.NETWORK_TRAFFIC_AUTOHIDE_THRESHOLD, 1, UserHandle.USER_CURRENT); + setGravity(Gravity.CENTER); + setMaxLines(2); + setSpacingAndFonts(); + updateTrafficDrawable(); setVisibility(View.GONE); + mVisible = false; } private void clearHandlerCallbacks() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java index f4b4299c055..a12353f6e68 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java @@ -127,9 +127,10 @@ public void setVisibleState(int state, boolean mIsEnabled) { @Override protected void makeVisible() { - setVisibility( - !mStatusbarExpanded && mSystemIconVisible && !mKeyguardShowing ? View.VISIBLE + boolean show = !mStatusbarExpanded && mSystemIconVisible && !mKeyguardShowing; + setVisibility(show ? View.VISIBLE : View.GONE); + mVisible = show; } @Override @@ -147,22 +148,27 @@ public void onPanelExpanded(boolean isExpanded) { mStatusbarExpanded = isExpanded; if (isExpanded) { setVisibility(View.GONE); + mVisible = false; + } else { + maybeRestoreVisibility(); } - maybeRestoreVisibility(); } public void setKeyguardShowing(boolean showing) { mKeyguardShowing = showing; if (showing) { setVisibility(View.GONE); + mVisible = false; + } else { + maybeRestoreVisibility(); } - maybeRestoreVisibility(); } private void maybeRestoreVisibility() { - if (mIsEnabled && !mStatusbarExpanded && !mKeyguardShowing && mSystemIconVisible + if (!mVisible && mIsEnabled && !mStatusbarExpanded && !mKeyguardShowing && mSystemIconVisible && restoreViewQuickly()) { setVisibility(View.VISIBLE); + mVisible = true; // then let the traffic handler do its checks update(); } From 4ac7aa1499b2fe8e22b8dd2305a4ce3069588471 Mon Sep 17 00:00:00 2001 From: Pranav Vashi Date: Sun, 14 Jun 2020 09:08:50 +0200 Subject: [PATCH 34/51] NetworkTraffic: Fix speed format for 10*KB Change-Id: I86153e8a5a314f0f44b02500878b68970a070155 --- .../com/android/systemui/statusbar/policy/NetworkTraffic.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java index 189808d0ea7..2b46b12003b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTraffic.java @@ -148,7 +148,7 @@ private CharSequence formatDecimal(long speed) { } else if (speed >= 10 * KB) { decimalFormat = new DecimalFormat("00.0"); unit = "KB"; - formatSpeed = decimalFormat.format(speed / (float)MB); + formatSpeed = decimalFormat.format(speed / (float)KB); } else { decimalFormat = new DecimalFormat("0.00"); unit = "KB"; From ad323e3c3a77626797fef5ff11a1df593e5b8b3d Mon Sep 17 00:00:00 2001 From: ganeshi4u Date: Sat, 24 Oct 2020 10:46:24 +0000 Subject: [PATCH 35/51] Traffic indicators: Switch quick statusbar header to LinearLayout Change-Id: I6274b370e0154927fb90131612789fcb3a4f2c9e --- .../res/layout/quick_status_bar_header_system_icons.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml index d72e0813fc7..7005a1bc8a5 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml @@ -57,7 +57,7 @@ Date: Sat, 13 Feb 2021 13:28:23 +0530 Subject: [PATCH 36/51] SystemUI: NetworkTraffic: Add notch check and allow devices to override * devices like surya have a small hole-punch cutout that can easily fit the network traffic monitor in the statusbar along with the other icons, for such devices, override the notch check by setting config_forceShowNetworkTrafficOnStatusBar to true in SystemUI overlay. Change-Id: Iebce2052f4e4cccf96c44a7ce42ef31abe6ca23b --- .../SystemUI/res/values/custom_config.xml | 3 +++ .../statusbar/policy/NetworkTrafficSB.java | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/res/values/custom_config.xml b/packages/SystemUI/res/values/custom_config.xml index 3163b2ac854..fc309c00582 100644 --- a/packages/SystemUI/res/values/custom_config.xml +++ b/packages/SystemUI/res/values/custom_config.xml @@ -35,4 +35,7 @@ This allows for the first block in PathEffect to fade --> 2 + + false + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java index a12353f6e68..9d388d41183 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java @@ -11,9 +11,8 @@ import android.util.AttributeSet; import android.view.View; -import com.android.internal.util.custom.CustomUtils; - import com.android.systemui.Dependency; +import com.android.systemui.R; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.statusbar.StatusIconDisplayable; @@ -63,7 +62,7 @@ protected void onDetachedFromWindow() { @Override protected void setMode() { super.setMode(); - mIsEnabled = mIsEnabled && !ArrowUtils.hasNotch(mContext); + mIsEnabled = mIsEnabled && shouldShowOnSB(mContext); } @Override @@ -172,6 +171,18 @@ && restoreViewQuickly()) { // then let the traffic handler do its checks update(); } - + } + + private static boolean shouldShowOnSB(Context context) { + if (context.getResources().getBoolean(R.bool.config_forceShowNetworkTrafficOnStatusBar)) + return true; + + int cutoutResId = context.getResources().getIdentifier("config_mainBuiltInDisplayCutout", + "string", "android"); + if (cutoutResId > 0) { + return context.getResources().getString(cutoutResId).equals(""); + } + + return true; } } From f7f0f861112f26cb942710ee2bb7eebffce4ea9c Mon Sep 17 00:00:00 2001 From: Adithya R Date: Sat, 13 Feb 2021 21:21:13 +0530 Subject: [PATCH 37/51] SystemUI: NetworkTraffic: Minor refinements - remove unwanted padding on top of expanded statusbar traffic indicator and center it properly - reduce side padding of statusbar indicator - show /S in caps - reduce overall text size and increase line spacing - use op slate medium font (600 weight) Change-Id: I9bc80ba00700c5a184cce2b6703d11986203739b --- .../layout/quick_status_bar_header_system_icons.xml | 7 +++---- .../statusbar/phone/StatusBarIconController.java | 2 +- .../systemui/statusbar/policy/NetworkTraffic.java | 10 +++++----- .../systemui/statusbar/policy/NetworkTrafficSB.java | 8 ++++---- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml index 7005a1bc8a5..8eebc6cd395 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml @@ -57,15 +57,14 @@ + android:gravity="center_vertical|end"/> Date: Wed, 24 Feb 2021 15:30:13 +0530 Subject: [PATCH 38/51] SystemUI: Reduce statusbar network speed margins Change-Id: I0d031048a5499508138f04f7be2ae12819d4ee69 --- .../systemui/statusbar/phone/StatusBarIconController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java index 581d7585126..e1d84f03a8a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -325,7 +325,7 @@ private StatusBarMobileView onCreateStatusBarMobileView(String slot) { private NetworkTrafficSB onCreateNetworkTraffic(String slot) { NetworkTrafficSB view = new NetworkTrafficSB(mContext); - view.setPadding(3, 0, 3, 0); + view.setPadding(2, 0, 2, 0); return view; } From 12c4dbd8a4968097e4efb1d6ea31feb5f5ed6aa4 Mon Sep 17 00:00:00 2001 From: Adithya R Date: Sun, 11 Apr 2021 01:17:48 +0530 Subject: [PATCH 39/51] SystemUI: NetworkTrafficSB: Reduce font size a bit Change-Id: I929c46884a698bc7ea2f406a0a2e7d522b9c69e8 --- .../com/android/systemui/statusbar/policy/NetworkTrafficSB.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java index 9316db1083c..82c884e48d3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkTrafficSB.java @@ -73,7 +73,7 @@ protected void setSpacingAndFonts() { @Override protected RelativeSizeSpan getSpeedRelativeSizeSpan() { - return new RelativeSizeSpan(0.72f); + return new RelativeSizeSpan(0.70f); } @Override From 1388e80b94eb627774a9a8ac88e6d7a300624f13 Mon Sep 17 00:00:00 2001 From: cjybyjk Date: Fri, 22 Jan 2021 17:12:07 +0800 Subject: [PATCH 40/51] base: add MAC address firewall [1/2] Signed-off-by: cjybyjk Change-Id: I2052c7f64d1cb7d9e0907b60cc144f172d2f4bfb --- core/java/android/os/INetworkManagementService.aidl | 1 + .../com/android/server/NetworkManagementService.java | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 0cce19222d2..2bbff4b5002 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -323,6 +323,7 @@ interface INetworkManagementService void setFirewallInterfaceRule(String iface, boolean allow); void setFirewallUidRule(int chain, int uid, int rule); void setFirewallUidRules(int chain, in int[] uids, in int[] rules); + void setFirewallMACAddressRule(String macAddr, boolean allow); void setFirewallChainEnabled(int chain, boolean enable); /** diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 0ddfa1c16a0..a7f9675477a 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -1600,6 +1600,17 @@ public void setFirewallInterfaceRule(String iface, boolean allow) { } } + @Override + public void setFirewallMACAddressRule(String macAddr, boolean allow) { + enforceSystemUid(); + try { + mNetdService.firewallSetMACAddressRule(macAddr, + allow ? INetd.FIREWALL_RULE_ALLOW : INetd.FIREWALL_RULE_DENY); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); + } + } + private void closeSocketsForFirewallChainLocked(int chain, String chainName) { // UID ranges to close sockets on. UidRangeParcel[] ranges; From 53e4d6657b399ef83532ade14d38fb179a8e71e6 Mon Sep 17 00:00:00 2001 From: LibXZR Date: Thu, 17 Mar 2022 22:58:19 +0800 Subject: [PATCH 41/51] base: Add support for application downgrade Can be useful in some cases. Change-Id: I999337cc55e9675cedde35191a6438d90744e5aa Signed-off-by: LibXZR --- core/java/android/provider/Settings.java | 6 ++++++ .../java/com/android/server/pm/PackageManagerService.java | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index c4b1f81513e..98dabb27de4 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -15734,6 +15734,12 @@ public static boolean putFloat(ContentResolver cr, String name, float value) { */ public static final String NR_NSA_TRACKING_SCREEN_OFF_MODE = "nr_nsa_tracking_screen_off_mode"; + + /** + * Control whether application downgrade is allowed. + * @hide + */ + public static final String PM_DOWNGRADE_ALLOWED = "pm_downgrade_allowed"; } /** diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index a752f85ad36..931c87a9c45 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -15109,7 +15109,9 @@ private int installLocationPolicy(PackageInfoLite pkgLite) { if (dataOwnerPkg != null) { if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, - dataOwnerPkg.isDebuggable())) { + dataOwnerPkg.isDebuggable()) + && Global.getInt(mContext.getContentResolver(), + Global.PM_DOWNGRADE_ALLOWED, 0) == 0) { try { checkDowngrade(dataOwnerPkg, pkgLite); } catch (PackageManagerException e) { From 147cffacc9c7b58831c466cab8372b12e30fcf71 Mon Sep 17 00:00:00 2001 From: LibXZR Date: Fri, 18 Mar 2022 10:12:37 +0800 Subject: [PATCH 42/51] base: Add support for window ignore secure Feature: yt/KSCOPE-23 Change-Id: Ia9447ca17f6b24152b64526c25710a77e1388ce6 Signed-off-by: LibXZR fix derp --- core/java/android/provider/Settings.java | 6 ++++++ core/java/android/view/Window.java | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 98dabb27de4..172ef52b7c8 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10293,6 +10293,12 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val */ public static final String SWAP_CAPACITIVE_KEYS = "swap_capacitive_keys"; + /** + * Control whether FLAG_SECURE is ignored for all windows. + * @hide + */ + public static final String WINDOW_IGNORE_SECURE = "window_ignore_secure"; + /** * These entries are considered common between the personal and the managed profile, * since the managed profile doesn't get to change them. diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index b399691ca78..3b86a6c9b8b 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -17,6 +17,7 @@ package android.view; import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; +import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import android.annotation.ColorInt; import android.annotation.DrawableRes; @@ -45,6 +46,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; +import android.provider.Settings; import android.transition.Scene; import android.transition.Transition; import android.transition.TransitionManager; @@ -1191,6 +1193,10 @@ public void clearPrivateFlags(int flags) { * @see #clearFlags */ public void setFlags(int flags, int mask) { + if ((mask & FLAG_SECURE) != 0 && Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.WINDOW_IGNORE_SECURE, 0) == 1) { + mask &= ~FLAG_SECURE; + } final WindowManager.LayoutParams attrs = getAttributes(); attrs.flags = (attrs.flags&~mask) | (flags&mask); mForcedWindowFlags |= mask; From 9b0c7932f65ec2a124229ee80f1b7bc2b4da8666 Mon Sep 17 00:00:00 2001 From: Binhong Wang Date: Tue, 2 Aug 2022 11:49:49 +0800 Subject: [PATCH 43/51] ResolveActivity scroll not Smooth Root Cause: ResolveActivity doesn't enable hardware accelerated. Soluton: Add ActivityInfo.FLAG_HARDWARE_ACCELERATED Change-Id: I1537cd8cedd75385679cfe19e90696b5a9b5fae5 Signed-off-by: Pranav Vashi --- .../core/java/com/android/server/pm/PackageManagerService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 931c87a9c45..f507fd50ff4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -12458,7 +12458,8 @@ private void commitPackageSettings(AndroidPackage pkg, mResolveActivity.processName = "system:ui"; mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER; - mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; + mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS + | ActivityInfo.FLAG_HARDWARE_ACCELERATED; mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert; mResolveActivity.exported = true; mResolveActivity.enabled = true; From 685b9d8415b10a91474bee56f6901efa2478a9e6 Mon Sep 17 00:00:00 2001 From: timjosten Date: Thu, 28 Jul 2022 01:22:27 +0000 Subject: [PATCH 44/51] SystemUI: Fix QS expand lag when VoLTE/VoWiFi icons are enabled Signed-off-by: Pranav Vashi --- .../systemui/statusbar/policy/MobileSignalController.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index fcb97ef643e..c23a0e44d1c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -78,6 +78,7 @@ public class MobileSignalController extends SignalController< private final String mNetworkNameDefault; private final String mNetworkNameSeparator; private final ContentObserver mObserver; + private final Handler mHandler = new Handler(); @VisibleForTesting final PhoneStateListener mPhoneStateListener; // Save entire info for logging, we only use the id. @@ -600,6 +601,7 @@ private void removeListeners() { @Override public void notifyListeners(SignalCallback callback) { + mHandler.post(() -> { MobileIconGroup icons = getIcons(); String contentDescription = getTextIfExists(getContentDescription()).toString(); @@ -654,6 +656,7 @@ public void notifyListeners(SignalCallback callback) { activityIn, activityOut, volteIcon, dataContentDescription, dataContentDescriptionHtml, description, icons.mIsWide, mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming); + }); } @Override From 914450fbbdef4a5349f9ba2f544c416f92def00a Mon Sep 17 00:00:00 2001 From: Pranav Vashi Date: Fri, 31 Dec 2021 23:44:59 +0530 Subject: [PATCH 45/51] InputMethodUtils: Fix system bootloop when no IME found * In case of faulty gapps, there are no default IME left on the system. This shouldn't be situation where user cannot boot at all. * Handle InputMethodUtils to prevent PackageManagerService crashing system. Log: 12-31 23:07:42.668 2559 2559 E System : ****************************************** 12-31 23:07:42.668 2559 2559 E System : ************ Failure starting system services 12-31 23:07:42.668 2559 2559 E System : java.lang.RuntimeException: Failed to boot service com.android.server.inputmethod.InputMethodManagerService$Lifecycle: onBootPhase threw an exception during phase 550 12-31 23:07:42.668 2559 2559 E System : at com.android.server.SystemServiceManager.startBootPhase(SystemServiceManager.java:211) 12-31 23:07:42.668 2559 2559 E System : at com.android.server.SystemServer.lambda$startOtherServices$6$SystemServer(SystemServer.java:2294) 12-31 23:07:42.668 2559 2559 E System : at com.android.server.SystemServer$$ExternalSyntheticLambda4.run(Unknown Source:30) 12-31 23:07:42.668 2559 2559 E System : at com.android.server.am.ActivityManagerService.systemReady(ActivityManagerService.java:9653) 12-31 23:07:42.668 2559 2559 E System : at com.android.server.SystemServer.startOtherServices(SystemServer.java:2291) 12-31 23:07:42.668 2559 2559 E System : at com.android.server.SystemServer.run(SystemServer.java:608) 12-31 23:07:42.668 2559 2559 E System : at com.android.server.SystemServer.main(SystemServer.java:424) 12-31 23:07:42.668 2559 2559 E System : at java.lang.reflect.Method.invoke(Native Method) 12-31 23:07:42.668 2559 2559 E System : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 12-31 23:07:42.668 2559 2559 E System : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:925) 12-31 23:07:42.668 2559 2559 E System : Caused by: java.lang.IllegalArgumentException: Unknown package: com.google.android.inputmethod.latin 12-31 23:07:42.668 2559 2559 E System : at com.android.server.pm.PackageManagerService.getApplicationEnabledSetting(PackageManagerService.java:21539) 12-31 23:07:42.668 2559 2559 E System : at com.android.server.inputmethod.InputMethodUtils.setDisabledUntilUsed(InputMethodUtils.java:681) 12-31 23:07:42.668 2559 2559 E System : at com.android.server.inputmethod.InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(InputMethodUtils.java:673) 12-31 23:07:42.668 2559 2559 E System : at com.android.server.inputmethod.InputMethodManagerService.systemRunning(InputMethodManagerService.java:1913) 12-31 23:07:42.668 2559 2559 E System : at com.android.server.inputmethod.InputMethodManagerService$Lifecycle.onBootPhase(InputMethodManagerService.java:1636) 12-31 23:07:42.668 2559 2559 E System : at com.android.server.SystemServiceManager.startBootPhase(SystemServiceManager.java:208) 12-31 23:07:42.668 2559 2559 E System : ... 9 more 12-31 23:07:42.668 2559 2559 E Zygote : System zygote died with exception 12-31 23:07:42.668 2559 2559 E Zygote : java.lang.RuntimeException: Failed to boot service com.android.server.inputmethod.InputMethodManagerService$Lifecycle: onBootPhase threw an exception during phase 550 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.SystemServiceManager.startBootPhase(SystemServiceManager.java:211) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.SystemServer.lambda$startOtherServices$6$SystemServer(SystemServer.java:2294) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.SystemServer$$ExternalSyntheticLambda4.run(Unknown Source:30) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.am.ActivityManagerService.systemReady(ActivityManagerService.java:9653) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.SystemServer.startOtherServices(SystemServer.java:2291) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.SystemServer.run(SystemServer.java:608) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.SystemServer.main(SystemServer.java:424) 12-31 23:07:42.668 2559 2559 E Zygote : at java.lang.reflect.Method.invoke(Native Method) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:925) 12-31 23:07:42.668 2559 2559 E Zygote : Caused by: java.lang.IllegalArgumentException: Unknown package: com.google.android.inputmethod.latin 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.pm.PackageManagerService.getApplicationEnabledSetting(PackageManagerService.java:21539) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.inputmethod.InputMethodUtils.setDisabledUntilUsed(InputMethodUtils.java:681) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.inputmethod.InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(InputMethodUtils.java:673) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.inputmethod.InputMethodManagerService.systemRunning(InputMethodManagerService.java:1913) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.inputmethod.InputMethodManagerService$Lifecycle.onBootPhase(InputMethodManagerService.java:1636) 12-31 23:07:42.668 2559 2559 E Zygote : at com.android.server.SystemServiceManager.startBootPhase(SystemServiceManager.java:208) 12-31 23:07:42.668 2559 2559 E Zygote : ... 9 more 12-31 23:07:42.668 2559 2559 D AndroidRuntime: Shutting down VM 12-31 23:07:42.669 2559 2559 E AndroidRuntime: *** FATAL EXCEPTION IN SYSTEM PROCESS: main 12-31 23:07:42.669 2559 2559 E AndroidRuntime: java.lang.RuntimeException: Failed to boot service com.android.server.inputmethod.InputMethodManagerService$Lifecycle: onBootPhase threw an exception during phase 550 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.SystemServiceManager.startBootPhase(SystemServiceManager.java:211) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.SystemServer.lambda$startOtherServices$6$SystemServer(SystemServer.java:2294) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.SystemServer$$ExternalSyntheticLambda4.run(Unknown Source:30) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.am.ActivityManagerService.systemReady(ActivityManagerService.java:9653) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.SystemServer.startOtherServices(SystemServer.java:2291) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.SystemServer.run(SystemServer.java:608) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.SystemServer.main(SystemServer.java:424) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:925) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: Caused by: java.lang.IllegalArgumentException: Unknown package: com.google.android.inputmethod.latin 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.pm.PackageManagerService.getApplicationEnabledSetting(PackageManagerService.java:21539) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.inputmethod.InputMethodUtils.setDisabledUntilUsed(InputMethodUtils.java:681) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.inputmethod.InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(InputMethodUtils.java:673) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.inputmethod.InputMethodManagerService.systemRunning(InputMethodManagerService.java:1913) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.inputmethod.InputMethodManagerService$Lifecycle.onBootPhase(InputMethodManagerService.java:1636) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: at com.android.server.SystemServiceManager.startBootPhase(SystemServiceManager.java:208) 12-31 23:07:42.669 2559 2559 E AndroidRuntime: ... 9 more Signed-off-by: Pranav Vashi --- .../java/com/android/server/inputmethod/InputMethodUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java index 77e2fbd2567..1c255e3fca0 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java @@ -679,7 +679,7 @@ private static void setDisabledUntilUsed(IPackageManager packageManager, String final int state; try { state = packageManager.getApplicationEnabledSetting(packageName, userId); - } catch (RemoteException e) { + } catch (Exception e) { Slog.w(TAG, "getApplicationEnabledSetting failed. packageName=" + packageName + " userId=" + userId, e); return; @@ -693,7 +693,7 @@ private static void setDisabledUntilUsed(IPackageManager packageManager, String packageManager.setApplicationEnabledSetting(packageName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED, 0 /* newState */, userId, callingPackage); - } catch (RemoteException e) { + } catch (Exception e) { Slog.w(TAG, "setApplicationEnabledSetting failed. packageName=" + packageName + " userId=" + userId + " callingPackage=" + callingPackage, e); return; From 0827e7c0a2d17bb806eb34338fd9221567d3f089 Mon Sep 17 00:00:00 2001 From: StarkDroid Date: Sun, 9 Apr 2023 10:09:44 +0700 Subject: [PATCH 46/51] [1/2] Statusbar Clock background chip Inspired by looking at few magisk/substratum module :P Signed-off-by: StarkDroid Signed-off-by: Rahmad Adi Pratama --- core/java/android/provider/Settings.java | 11 +++++++++- packages/SystemUI/res/drawable/sb_date_bg.xml | 6 ++++++ packages/SystemUI/res/layout/status_bar.xml | 6 ++++-- .../phone/CollapsedStatusBarFragment.java | 20 +++++++++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 packages/SystemUI/res/drawable/sb_date_bg.xml diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 172ef52b7c8..089c45c01a7 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5589,7 +5589,15 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean * 1 - Right of clock * @hide */ - public static final String STATUSBAR_CLOCK_DATE_POSITION = "statusbar_clock_date_position"; + public static final String STATUSBAR_CLOCK_DATE_POSITION = "statusbar_clock_date_position"; + + /** + * Statusbar clock background + * 0 - hide accented chip + * 1 - show accented chip (default) + * @hide + */ + public static final String STATUSBAR_CLOCK_CHIP = "statusbar_clock_chip"; /** * Whether to show the notification ticker on the status bar @@ -5960,6 +5968,7 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean PRIVATE_SETTINGS.add(STATUSBAR_CLOCK_DATE_STYLE); PRIVATE_SETTINGS.add(STATUSBAR_CLOCK_DATE_FORMAT); PRIVATE_SETTINGS.add(STATUSBAR_CLOCK_DATE_POSITION); + PRIVATE_SETTINGS.add(STATUSBAR_CLOCK_CHIP); PRIVATE_SETTINGS.add(ACCENT_COLOR); PRIVATE_SETTINGS.add(USE_WALL_ACCENT); PRIVATE_SETTINGS.add(AUTO_ACCENT_TYPE); diff --git a/packages/SystemUI/res/drawable/sb_date_bg.xml b/packages/SystemUI/res/drawable/sb_date_bg.xml new file mode 100644 index 00000000000..b5e0acd088c --- /dev/null +++ b/packages/SystemUI/res/drawable/sb_date_bg.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index 37d3091ddc9..7e8bf517819 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -75,13 +75,14 @@ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java index 997c7ed1124..a046c16c0c9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java @@ -81,6 +81,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private LinearLayout mCenterClockLayout; private View mRightClock; private boolean mShowClock = true; + private boolean mShowSBClockBg = true; private final Handler mHandler = new Handler(); private BatteryMeterView mBatteryMeterView; private StatusIconContainer mStatusIcons; @@ -98,6 +99,9 @@ void observe() { mContentResolver.registerContentObserver(Settings.System.getUriFor( Settings.System.STATUSBAR_CLOCK_STYLE), false, this, UserHandle.USER_ALL); + mContentResolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.STATUSBAR_CLOCK_CHIP), + false, this, UserHandle.USER_ALL); } @Override @@ -462,6 +466,22 @@ public void updateSettings(boolean animate) { Settings.System.STATUSBAR_CLOCK_STYLE, 0, UserHandle.USER_CURRENT); } + + mShowSBClockBg = Settings.System.getIntForUser(mContentResolver, + Settings.System.STATUSBAR_CLOCK_CHIP, 1, + UserHandle.USER_CURRENT) == 1; + + if (mShowSBClockBg) { + mClockView.setBackgroundResource(R.drawable.sb_date_bg); + mClockView.setPadding(10,5,10,5); + mRightClock.setBackgroundResource(R.drawable.sb_date_bg); + mRightClock.setPadding(10,5,10,5); + } else { + mClockView.setBackgroundResource(0); + mClockView.setPadding(0,0,0,0); + mRightClock.setBackgroundResource(0); + mRightClock.setPadding(0,0,0,0); + } updateClockStyle(animate); } From 390f116a360e5a92ca7373aff9e5560bc4cc3fea Mon Sep 17 00:00:00 2001 From: Pranav Vashi Date: Tue, 18 Jan 2022 14:39:11 +0530 Subject: [PATCH 47/51] ThemeOverlayManager: Apply wifi and signal icon styles last Signed-off-by: Pranav Vashi --- .../android/systemui/theme/ThemeOverlayManager.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java index 665cb6307b6..adfb096f7fe 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java @@ -67,6 +67,12 @@ class ThemeOverlayManager { @VisibleForTesting static final String OVERLAY_CATEGORY_ICON_THEME_PICKER = "android.theme.customization.icon_pack.themepicker"; + @VisibleForTesting + static final String OVERLAY_CATEGORY_ICON_SIGNAL = + "android.theme.customization.signal_icon"; + @VisibleForTesting + static final String OVERLAY_CATEGORY_ICON_WIFI = + "android.theme.customization.wifi_icon"; /* * All theme customization categories used by the system, in order that they should be applied, @@ -80,7 +86,9 @@ class ThemeOverlayManager { OVERLAY_CATEGORY_ICON_ANDROID, OVERLAY_CATEGORY_ICON_SYSUI, OVERLAY_CATEGORY_ICON_SETTINGS, - OVERLAY_CATEGORY_ICON_THEME_PICKER); + OVERLAY_CATEGORY_ICON_THEME_PICKER, + OVERLAY_CATEGORY_ICON_SIGNAL, + OVERLAY_CATEGORY_ICON_WIFI); /* Categories that need to applied to the current user as well as the system user. */ @VisibleForTesting @@ -125,6 +133,8 @@ class ThemeOverlayManager { mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_SETTINGS, SETTINGS_PACKAGE); mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_LAUNCHER, mLauncherPackage); mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_THEME_PICKER, mThemePickerPackage); + mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_SIGNAL, SYSUI_PACKAGE); + mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_WIFI, SYSUI_PACKAGE); } /** From 464804b05d267f3647927dfa4b9b5dacbc2e5e7f Mon Sep 17 00:00:00 2001 From: darknius09 Date: Sat, 27 May 2023 13:25:52 +0000 Subject: [PATCH 48/51] base: import ThemeUtils --- .../internal/util/custom/ThemeUtils.java | 246 ++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 core/java/com/android/internal/util/custom/ThemeUtils.java diff --git a/core/java/com/android/internal/util/custom/ThemeUtils.java b/core/java/com/android/internal/util/custom/ThemeUtils.java new file mode 100644 index 00000000000..20cedfb1a45 --- /dev/null +++ b/core/java/com/android/internal/util/custom/ThemeUtils.java @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util.custom; + +import static android.os.UserHandle.USER_SYSTEM; + +import android.util.PathParser; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.om.IOverlayManager; +import android.content.om.OverlayInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ProviderInfo; +import android.content.res.Resources; +import android.content.res.Resources.NotFoundException; +import android.content.res.Configuration; +import android.database.Cursor; +import android.graphics.Typeface; +import android.graphics.Path; +import android.graphics.drawable.AdaptiveIconDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.PathShape; +import android.net.Uri; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class ThemeUtils { + + public static final String TAG = "ThemeUtils"; + + public static final String FONT_KEY = "android.theme.customization.font"; + public static final String ICON_SHAPE_KEY= "android.theme.customization.adaptive_icon_shape"; + + public static final Comparator OVERLAY_INFO_COMPARATOR = + Comparator.comparingInt(a -> a.priority); + + private Context mContext; + private IOverlayManager mOverlayManager; + private PackageManager pm; + private Resources overlayRes; + + public ThemeUtils(Context context) { + mContext = context; + mOverlayManager = IOverlayManager.Stub + .asInterface(ServiceManager.getService(Context.OVERLAY_SERVICE)); + pm = context.getPackageManager(); + } + + public void setOverlayEnabled(String category, String packageName) { + final String currentPackageName = getOverlayInfos(category).stream() + .filter(info -> info.isEnabled()) + .map(info -> info.packageName) + .findFirst() + .orElse(null); + + try { + if ("android".equals(packageName)) { + mOverlayManager.setEnabled(currentPackageName, false, USER_SYSTEM); + } else { + mOverlayManager.setEnabledExclusiveInCategory(packageName, + USER_SYSTEM); + } + + writeSettings(category, packageName, "android".equals(packageName)); + + } catch (RemoteException e) { + } + } + + public void writeSettings(String category, String packageName, boolean disable) { + final String overlayPackageJson = Settings.Secure.getStringForUser( + mContext.getContentResolver(), + Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES, USER_SYSTEM); + JSONObject object; + try { + if (overlayPackageJson == null) { + object = new JSONObject(); + } else { + object = new JSONObject(overlayPackageJson); + } + if (disable) { + if (object.has(category)) object.remove(category); + } else { + object.put(category, packageName); + } + Settings.Secure.putStringForUser(mContext.getContentResolver(), + Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES, + object.toString(), USER_SYSTEM); + } catch (JSONException e) { + Log.e(TAG, "Failed to parse THEME_CUSTOMIZATION_OVERLAY_PACKAGES.", e); + } + } + + public List getOverlayPackagesForCategory(String category) { + return getOverlayPackagesForCategory(category, "android"); + } + + public List getOverlayPackagesForCategory(String category, String target) { + List overlays = new ArrayList<>(); + overlays.add("android"); + for (OverlayInfo info : getOverlayInfos(category, target)) { + if (category.equals(info.getCategory())) { + overlays.add(info.getPackageName()); + } + } + return overlays; + } + + public List getOverlayInfos(String category) { + return getOverlayInfos(category, "android"); + } + + public List getOverlayInfos(String category, String target) { + final List filteredInfos = new ArrayList<>(); + try { + List overlayInfos = mOverlayManager + .getOverlayInfosForTarget(target, USER_SYSTEM); + for (OverlayInfo overlayInfo : overlayInfos) { + if (category.equals(overlayInfo.category)) { + filteredInfos.add(overlayInfo); + } + } + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + filteredInfos.sort(OVERLAY_INFO_COMPARATOR); + return filteredInfos; + } + + public List getLabels(String category) { + List labels = new ArrayList<>(); + labels.add("Default"); + for (OverlayInfo info : getOverlayInfos(category)) { + if (category.equals(info.getCategory())) { + try { + labels.add(pm.getApplicationInfo(info.packageName, 0) + .loadLabel(pm).toString()); + } catch (PackageManager.NameNotFoundException e) { + labels.add(info.packageName); + } + } + } + return labels; + } + + public List getFonts() { + final List fontlist = new ArrayList<>(); + for (String overlayPackage : getOverlayPackagesForCategory(FONT_KEY)) { + try { + overlayRes = overlayPackage.equals("android") ? Resources.getSystem() + : pm.getResourcesForApplication(overlayPackage); + final String font = overlayRes.getString( + overlayRes.getIdentifier("config_bodyFontFamily", + "string", overlayPackage)); + fontlist.add(Typeface.create(font, Typeface.NORMAL)); + } catch (NameNotFoundException | NotFoundException e) { + // Do nothing + } + } + return fontlist; + } + + public List getShapeDrawables() { + final List shapelist = new ArrayList<>(); + for (String overlayPackage : getOverlayPackagesForCategory(ICON_SHAPE_KEY)) { + shapelist.add(createShapeDrawable(overlayPackage)); + } + return shapelist; + } + + public ShapeDrawable createShapeDrawable(String overlayPackage) { + try { + if (overlayPackage.equals("android")) { + overlayRes = Resources.getSystem(); + } else { + if (overlayPackage.equals("default")) overlayPackage = "android"; + overlayRes = pm.getResourcesForApplication(overlayPackage); + } + } catch (NameNotFoundException | NotFoundException e) { + // Do nothing + } + final String shape = overlayRes.getString( + overlayRes.getIdentifier("config_icon_mask", + "string", overlayPackage)); + Path path = TextUtils.isEmpty(shape) ? null : PathParser.createPathFromPathData(shape); + PathShape pathShape = new PathShape(path, 100f, 100f); + ShapeDrawable shapeDrawable = new ShapeDrawable(pathShape); + int mThumbSize = (int) (mContext.getResources().getDisplayMetrics().density * 72); + shapeDrawable.setIntrinsicHeight(mThumbSize); + shapeDrawable.setIntrinsicWidth(mThumbSize); + return shapeDrawable; + } + + public boolean isOverlayEnabled(String overlayPackage) { + try { + OverlayInfo info = mOverlayManager.getOverlayInfo(overlayPackage, USER_SYSTEM); + return info == null ? false : info.isEnabled(); + } catch (RemoteException e) { + e.printStackTrace(); + } + return false; + } + + public boolean isDefaultOverlay(String category) { + for (String overlayPackage : getOverlayPackagesForCategory(category)) { + try { + OverlayInfo info = mOverlayManager.getOverlayInfo(overlayPackage, USER_SYSTEM); + if (info != null && info.isEnabled()) { + return false; + } else { + continue; + } + } catch (RemoteException e) { + e.printStackTrace(); + } + } + return true; + } +} \ No newline at end of file From fcd92e767eddfdc64701dcd8dcb9e215bb2fb8f9 Mon Sep 17 00:00:00 2001 From: darknius09 Date: Sun, 28 May 2023 07:47:32 +0000 Subject: [PATCH 49/51] base: Custom Statusbar Signal & Wi-Fi icons --- .../internal/util/custom/ThemesUtils.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/core/java/com/android/internal/util/custom/ThemesUtils.java b/core/java/com/android/internal/util/custom/ThemesUtils.java index 42d02b62f28..71c6277a5a0 100644 --- a/core/java/com/android/internal/util/custom/ThemesUtils.java +++ b/core/java/com/android/internal/util/custom/ThemesUtils.java @@ -80,4 +80,28 @@ public static void stockNewTileStyle(IOverlayManager om, int userId) { } } } + + // Statusbar Signal icons + private static final String[] SIGNAL_BAR = { + "org.blissroms.systemui.signalbar_a", + "org.blissroms.systemui.signalbar_b", + "org.blissroms.systemui.signalbar_c", + "org.blissroms.systemui.signalbar_d", + "org.blissroms.systemui.signalbar_e", + "org.blissroms.systemui.signalbar_f", + "org.blissroms.systemui.signalbar_g", + "org.blissroms.systemui.signalbar_h", + }; + + // Statusbar Wifi icons + private static final String[] WIFI_BAR = { + "org.blissroms.systemui.wifibar_a", + "org.blissroms.systemui.wifibar_b", + "org.blissroms.systemui.wifibar_c", + "org.blissroms.systemui.wifibar_d", + "org.blissroms.systemui.wifibar_e", + "org.blissroms.systemui.wifibar_f", + "org.blissroms.systemui.wifibar_g", + "org.blissroms.systemui.wifibar_h", + }; } From 9ca83eef8d7d60a8f3002c854d8df7d097b0e1b3 Mon Sep 17 00:00:00 2001 From: darknius09 Date: Sun, 28 May 2023 07:47:49 +0000 Subject: [PATCH 50/51] Revert "ThemeOverlayManager: Apply wifi and signal icon styles last" This reverts commit 390f116a360e5a92ca7373aff9e5560bc4cc3fea. --- .../android/systemui/theme/ThemeOverlayManager.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java index adfb096f7fe..665cb6307b6 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java @@ -67,12 +67,6 @@ class ThemeOverlayManager { @VisibleForTesting static final String OVERLAY_CATEGORY_ICON_THEME_PICKER = "android.theme.customization.icon_pack.themepicker"; - @VisibleForTesting - static final String OVERLAY_CATEGORY_ICON_SIGNAL = - "android.theme.customization.signal_icon"; - @VisibleForTesting - static final String OVERLAY_CATEGORY_ICON_WIFI = - "android.theme.customization.wifi_icon"; /* * All theme customization categories used by the system, in order that they should be applied, @@ -86,9 +80,7 @@ class ThemeOverlayManager { OVERLAY_CATEGORY_ICON_ANDROID, OVERLAY_CATEGORY_ICON_SYSUI, OVERLAY_CATEGORY_ICON_SETTINGS, - OVERLAY_CATEGORY_ICON_THEME_PICKER, - OVERLAY_CATEGORY_ICON_SIGNAL, - OVERLAY_CATEGORY_ICON_WIFI); + OVERLAY_CATEGORY_ICON_THEME_PICKER); /* Categories that need to applied to the current user as well as the system user. */ @VisibleForTesting @@ -133,8 +125,6 @@ class ThemeOverlayManager { mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_SETTINGS, SETTINGS_PACKAGE); mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_LAUNCHER, mLauncherPackage); mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_THEME_PICKER, mThemePickerPackage); - mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_SIGNAL, SYSUI_PACKAGE); - mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_WIFI, SYSUI_PACKAGE); } /** From fcf8867523a4e3e60ac8527a4b89c64d960ab421 Mon Sep 17 00:00:00 2001 From: darknius09 Date: Sun, 28 May 2023 08:07:39 +0000 Subject: [PATCH 51/51] Network Traffic: Fix up padding --- .../res/layout/quick_status_bar_header_system_icons.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml index 8eebc6cd395..6b1bf7917ee 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml @@ -59,8 +59,8 @@ android:id="@+id/networkTraffic" android:layout_width="wrap_content" android:layout_height="match_parent" - android:layout_marginStart="6dp" - android:layout_marginEnd="4dp" + android:layout_marginStart="2dp" + android:layout_marginEnd="2dp" android:singleLine="false" android:lineSpacingMultiplier="1.2" systemui:showDark="false"