Loading core/java/android/view/PointerIcon.java +12 −5 Original line number Diff line number Diff line Loading @@ -284,7 +284,7 @@ public final class PointerIcon implements Parcelable { if (bitmap == null) { throw new IllegalArgumentException("bitmap must not be null"); } validateHotSpot(bitmap, hotSpotX, hotSpotY); validateHotSpot(bitmap, hotSpotX, hotSpotY, false /* isScaled */); PointerIcon icon = new PointerIcon(TYPE_CUSTOM); icon.mBitmap = bitmap; Loading Loading @@ -517,7 +517,9 @@ public final class PointerIcon implements Parcelable { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; final Bitmap bitmap = getBitmapFromDrawable(bitmapDrawable); validateHotSpot(bitmap, hotSpotX, hotSpotY); // The bitmap and hotspot are loaded from the context, which means it is implicitly scaled // to the current display density, so treat this as a scaled icon when verifying hotspot. validateHotSpot(bitmap, hotSpotX, hotSpotY, true /* isScaled */); // Set the properties now that we have successfully loaded the icon. mBitmap = bitmap; mHotSpotX = hotSpotX; Loading @@ -531,11 +533,16 @@ public final class PointerIcon implements Parcelable { + ", hotspotX=" + mHotSpotX + ", hotspotY=" + mHotSpotY + "}"; } private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY) { if (hotSpotX < 0 || hotSpotX >= bitmap.getWidth()) { private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY, boolean isScaled) { // Be more lenient when checking the hotspot for scaled icons to account for the restriction // that bitmaps must have an integer size. if (hotSpotX < 0 || (isScaled ? (int) hotSpotX > bitmap.getWidth() : hotSpotX >= bitmap.getWidth())) { throw new IllegalArgumentException("x hotspot lies outside of the bitmap area"); } if (hotSpotY < 0 || hotSpotY >= bitmap.getHeight()) { if (hotSpotY < 0 || (isScaled ? (int) hotSpotY > bitmap.getHeight() : hotSpotY >= bitmap.getHeight())) { throw new IllegalArgumentException("y hotspot lies outside of the bitmap area"); } } Loading core/res/res/drawable/pointer_handwriting_icon.xml +1 −1 Original line number Diff line number Diff line Loading @@ -2,4 +2,4 @@ <pointer-icon xmlns:android="http://schemas.android.com/apk/res/android" android:bitmap="@drawable/pointer_handwriting" android:hotSpotX="8.25dp" android:hotSpotY="23.50dp" /> No newline at end of file android:hotSpotY="23.75dp" /> No newline at end of file core/res/res/drawable/pointer_handwriting_vector_icon.xml +1 −1 Original line number Diff line number Diff line Loading @@ -2,4 +2,4 @@ <pointer-icon xmlns:android="http://schemas.android.com/apk/res/android" android:bitmap="@drawable/pointer_handwriting_vector" android:hotSpotX="8.25dp" android:hotSpotY="23.50dp" /> No newline at end of file android:hotSpotY="23.75dp" /> No newline at end of file packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractBatteryStatusPreferenceController.java 0 → 100644 +155 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.settingslib.deviceinfo; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.BatteryManager; import android.os.Handler; import android.os.Message; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; import com.android.settingslib.R; import java.lang.ref.WeakReference; /** * Preference controller for battery status */ public abstract class AbstractBatteryStatusPreferenceController extends AbstractPreferenceController implements LifecycleObserver, OnStart, OnStop { @VisibleForTesting static final String KEY_BATTERY_STATUS = "battery_status"; private static final int EVENT_UPDATE_BATTERY = 700; private Preference mBatteryStatus; private Handler mHandler; private Context mContext; public AbstractBatteryStatusPreferenceController(Context context, Lifecycle lifecycle) { super(context); mContext = context; if (lifecycle != null) { lifecycle.addObserver(this); } } @Override public void onStart() { getHandler().sendEmptyMessage(EVENT_UPDATE_BATTERY); } @Override public void onStop() { getHandler().removeMessages(EVENT_UPDATE_BATTERY); } @Override public boolean isAvailable() { Intent intent = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); return intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false); } @Override public String getPreferenceKey() { return KEY_BATTERY_STATUS; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mBatteryStatus = screen.findPreference(KEY_BATTERY_STATUS); updateBattery(); } private Handler getHandler() { if (mHandler == null) { mHandler = new BatteryStatusHandler(this); } return mHandler; } private void updateBattery() { Intent intent = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); if (mBatteryStatus != null) { String batterystatus = mContext.getString(R.string.battery_info_status_unknown); String batterylevel = Integer.toString(Math.round(100.f * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100) / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100))) + "%"; switch (intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)) { case BatteryManager.BATTERY_STATUS_CHARGING: batterystatus = mContext.getString(R.string.battery_info_status_charging); break; case BatteryManager.BATTERY_STATUS_DISCHARGING: batterystatus = mContext.getString(R.string.battery_info_status_discharging); break; case BatteryManager.BATTERY_STATUS_FULL: batterystatus = mContext.getString(R.string.battery_info_status_full); break; case BatteryManager.BATTERY_STATUS_NOT_CHARGING: batterystatus = mContext.getString(R.string.battery_info_status_not_charging); break; case BatteryManager.BATTERY_STATUS_UNKNOWN: default: break; } mBatteryStatus.setSummary(batterylevel + " - " + batterystatus); } } private static class BatteryStatusHandler extends Handler { private WeakReference<AbstractBatteryStatusPreferenceController> mStatus; BatteryStatusHandler(AbstractBatteryStatusPreferenceController activity) { mStatus = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { AbstractBatteryStatusPreferenceController status = mStatus.get(); if (status == null) { return; } switch (msg.what) { case EVENT_UPDATE_BATTERY: status.updateBattery(); sendEmptyMessageDelayed(EVENT_UPDATE_BATTERY, 1000); break; default: throw new IllegalStateException("Unknown message " + msg.what); } } } } packages/SystemUI/res/values/cm_strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -137,4 +137,7 @@ <string name="screenrecord_skip_time_summary">Remove the 3 second wait</string> <string name="screenrecord_hevc_switch_label">HEVC encoding</string> <string name="screenrecord_hevc_switch_summary">Use the more efficient HEVC encoder</string> <!-- Channel name for Battery notifications --> <string name="battery_notification_channel_tv">Battery warning</string> </resources> Loading
core/java/android/view/PointerIcon.java +12 −5 Original line number Diff line number Diff line Loading @@ -284,7 +284,7 @@ public final class PointerIcon implements Parcelable { if (bitmap == null) { throw new IllegalArgumentException("bitmap must not be null"); } validateHotSpot(bitmap, hotSpotX, hotSpotY); validateHotSpot(bitmap, hotSpotX, hotSpotY, false /* isScaled */); PointerIcon icon = new PointerIcon(TYPE_CUSTOM); icon.mBitmap = bitmap; Loading Loading @@ -517,7 +517,9 @@ public final class PointerIcon implements Parcelable { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; final Bitmap bitmap = getBitmapFromDrawable(bitmapDrawable); validateHotSpot(bitmap, hotSpotX, hotSpotY); // The bitmap and hotspot are loaded from the context, which means it is implicitly scaled // to the current display density, so treat this as a scaled icon when verifying hotspot. validateHotSpot(bitmap, hotSpotX, hotSpotY, true /* isScaled */); // Set the properties now that we have successfully loaded the icon. mBitmap = bitmap; mHotSpotX = hotSpotX; Loading @@ -531,11 +533,16 @@ public final class PointerIcon implements Parcelable { + ", hotspotX=" + mHotSpotX + ", hotspotY=" + mHotSpotY + "}"; } private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY) { if (hotSpotX < 0 || hotSpotX >= bitmap.getWidth()) { private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY, boolean isScaled) { // Be more lenient when checking the hotspot for scaled icons to account for the restriction // that bitmaps must have an integer size. if (hotSpotX < 0 || (isScaled ? (int) hotSpotX > bitmap.getWidth() : hotSpotX >= bitmap.getWidth())) { throw new IllegalArgumentException("x hotspot lies outside of the bitmap area"); } if (hotSpotY < 0 || hotSpotY >= bitmap.getHeight()) { if (hotSpotY < 0 || (isScaled ? (int) hotSpotY > bitmap.getHeight() : hotSpotY >= bitmap.getHeight())) { throw new IllegalArgumentException("y hotspot lies outside of the bitmap area"); } } Loading
core/res/res/drawable/pointer_handwriting_icon.xml +1 −1 Original line number Diff line number Diff line Loading @@ -2,4 +2,4 @@ <pointer-icon xmlns:android="http://schemas.android.com/apk/res/android" android:bitmap="@drawable/pointer_handwriting" android:hotSpotX="8.25dp" android:hotSpotY="23.50dp" /> No newline at end of file android:hotSpotY="23.75dp" /> No newline at end of file
core/res/res/drawable/pointer_handwriting_vector_icon.xml +1 −1 Original line number Diff line number Diff line Loading @@ -2,4 +2,4 @@ <pointer-icon xmlns:android="http://schemas.android.com/apk/res/android" android:bitmap="@drawable/pointer_handwriting_vector" android:hotSpotX="8.25dp" android:hotSpotY="23.50dp" /> No newline at end of file android:hotSpotY="23.75dp" /> No newline at end of file
packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractBatteryStatusPreferenceController.java 0 → 100644 +155 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.settingslib.deviceinfo; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.BatteryManager; import android.os.Handler; import android.os.Message; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; import com.android.settingslib.R; import java.lang.ref.WeakReference; /** * Preference controller for battery status */ public abstract class AbstractBatteryStatusPreferenceController extends AbstractPreferenceController implements LifecycleObserver, OnStart, OnStop { @VisibleForTesting static final String KEY_BATTERY_STATUS = "battery_status"; private static final int EVENT_UPDATE_BATTERY = 700; private Preference mBatteryStatus; private Handler mHandler; private Context mContext; public AbstractBatteryStatusPreferenceController(Context context, Lifecycle lifecycle) { super(context); mContext = context; if (lifecycle != null) { lifecycle.addObserver(this); } } @Override public void onStart() { getHandler().sendEmptyMessage(EVENT_UPDATE_BATTERY); } @Override public void onStop() { getHandler().removeMessages(EVENT_UPDATE_BATTERY); } @Override public boolean isAvailable() { Intent intent = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); return intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false); } @Override public String getPreferenceKey() { return KEY_BATTERY_STATUS; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mBatteryStatus = screen.findPreference(KEY_BATTERY_STATUS); updateBattery(); } private Handler getHandler() { if (mHandler == null) { mHandler = new BatteryStatusHandler(this); } return mHandler; } private void updateBattery() { Intent intent = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); if (mBatteryStatus != null) { String batterystatus = mContext.getString(R.string.battery_info_status_unknown); String batterylevel = Integer.toString(Math.round(100.f * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100) / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100))) + "%"; switch (intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)) { case BatteryManager.BATTERY_STATUS_CHARGING: batterystatus = mContext.getString(R.string.battery_info_status_charging); break; case BatteryManager.BATTERY_STATUS_DISCHARGING: batterystatus = mContext.getString(R.string.battery_info_status_discharging); break; case BatteryManager.BATTERY_STATUS_FULL: batterystatus = mContext.getString(R.string.battery_info_status_full); break; case BatteryManager.BATTERY_STATUS_NOT_CHARGING: batterystatus = mContext.getString(R.string.battery_info_status_not_charging); break; case BatteryManager.BATTERY_STATUS_UNKNOWN: default: break; } mBatteryStatus.setSummary(batterylevel + " - " + batterystatus); } } private static class BatteryStatusHandler extends Handler { private WeakReference<AbstractBatteryStatusPreferenceController> mStatus; BatteryStatusHandler(AbstractBatteryStatusPreferenceController activity) { mStatus = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { AbstractBatteryStatusPreferenceController status = mStatus.get(); if (status == null) { return; } switch (msg.what) { case EVENT_UPDATE_BATTERY: status.updateBattery(); sendEmptyMessageDelayed(EVENT_UPDATE_BATTERY, 1000); break; default: throw new IllegalStateException("Unknown message " + msg.what); } } } }
packages/SystemUI/res/values/cm_strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -137,4 +137,7 @@ <string name="screenrecord_skip_time_summary">Remove the 3 second wait</string> <string name="screenrecord_hevc_switch_label">HEVC encoding</string> <string name="screenrecord_hevc_switch_summary">Use the more efficient HEVC encoder</string> <!-- Channel name for Battery notifications --> <string name="battery_notification_channel_tv">Battery warning</string> </resources>