diff options
29 files changed, 730 insertions, 844 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 449729e18376..48df9e66be70 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -3933,6 +3933,9 @@ public class ActivityManager { * processes to reclaim memory; the system will take care of restarting * these processes in the future as needed. * + * <p class="note">Third party applications can only use this API to kill their own processes. + * </p> + * * @param packageName The name of the package whose processes are to * be killed. */ diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index d53ad17f07ef..e27af17ebc3d 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -61,7 +61,6 @@ import android.hardware.display.DisplayManager.DisplayListener; import android.os.Build; import android.os.Bundle; import android.os.Handler; -import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; @@ -181,9 +180,6 @@ public abstract class WallpaperService extends Service { private final ArrayList<Engine> mActiveEngines = new ArrayList<Engine>(); - private Handler mBackgroundHandler; - private HandlerThread mBackgroundThread; - static final class WallpaperCommand { String action; int x; @@ -202,6 +198,14 @@ public abstract class WallpaperService extends Service { */ public class Engine { IWallpaperEngineWrapper mIWallpaperEngine; + final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4); + final ArraySet<RectF> mLocalColorsToAdd = new ArraySet<>(4); + + // 2D matrix [x][y] to represent a page of a portion of a window + EngineWindowPage[] mWindowPages = new EngineWindowPage[0]; + Bitmap mLastScreenshot; + int mLastWindowPage = -1; + private boolean mResetWindowPages; // Copies from mIWallpaperEngine. HandlerCaller mCaller; @@ -263,27 +267,11 @@ public abstract class WallpaperService extends Service { final Object mLock = new Object(); boolean mOffsetMessageEnqueued; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) float mPendingXOffset; float mPendingYOffset; float mPendingXOffsetStep; float mPendingYOffsetStep; - - /** - * local color extraction related fields - * to be used by the background thread only (except the atomic boolean) - */ - final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4); - final ArraySet<RectF> mLocalColorsToAdd = new ArraySet<>(4); - private long mLastProcessLocalColorsTimestamp; - private AtomicBoolean mProcessLocalColorsPending = new AtomicBoolean(false); - private int mPixelCopyCount = 0; - // 2D matrix [x][y] to represent a page of a portion of a window - EngineWindowPage[] mWindowPages = new EngineWindowPage[0]; - Bitmap mLastScreenshot; - private boolean mResetWindowPages; - boolean mPendingSync; MotionEvent mPendingMove; boolean mIsInAmbientMode; @@ -292,8 +280,12 @@ public abstract class WallpaperService extends Service { private long mLastColorInvalidation; private final Runnable mNotifyColorsChanged = this::notifyColorsChanged; + // used to throttle processLocalColors + private long mLastProcessLocalColorsTimestamp; + private AtomicBoolean mProcessLocalColorsPending = new AtomicBoolean(false); private final Supplier<Long> mClockFunction; private final Handler mHandler; + private Display mDisplay; private Context mDisplayContext; private int mDisplayState; @@ -833,7 +825,7 @@ public abstract class WallpaperService extends Service { + "was not established."); } mResetWindowPages = true; - processLocalColors(); + processLocalColors(mPendingXOffset, mPendingXOffsetStep); } catch (RemoteException e) { Log.w(TAG, "Can't notify system because wallpaper connection was lost.", e); } @@ -1372,7 +1364,7 @@ public abstract class WallpaperService extends Service { resetWindowPages(); mSession.finishDrawing(mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE); - processLocalColors(); + processLocalColors(mPendingXOffset, mPendingXOffsetStep); } reposition(); reportEngineShown(shouldWaitForEngineShown()); @@ -1517,7 +1509,7 @@ public abstract class WallpaperService extends Service { if (!mDestroyed) { mVisible = visible; reportVisibility(); - if (mReportedVisible) processLocalColors(); + if (mReportedVisible) processLocalColors(mPendingXOffset, mPendingXOffsetStep); } else { AnimationHandler.requestAnimatorsEnabled(visible, this); } @@ -1601,41 +1593,31 @@ public abstract class WallpaperService extends Service { } // setup local color extraction data - processLocalColors(); + processLocalColors(xOffset, xOffsetStep); } /** * Thread-safe util to call {@link #processLocalColorsInternal} with a minimum interval of * {@link #PROCESS_LOCAL_COLORS_INTERVAL_MS} between two calls. */ - private void processLocalColors() { + private void processLocalColors(float xOffset, float xOffsetStep) { if (mProcessLocalColorsPending.compareAndSet(false, true)) { final long now = mClockFunction.get(); final long timeSinceLastColorProcess = now - mLastProcessLocalColorsTimestamp; final long timeToWait = Math.max(0, PROCESS_LOCAL_COLORS_INTERVAL_MS - timeSinceLastColorProcess); - mBackgroundHandler.postDelayed(() -> { + mHandler.postDelayed(() -> { mLastProcessLocalColorsTimestamp = now + timeToWait; mProcessLocalColorsPending.set(false); - processLocalColorsInternal(); + processLocalColorsInternal(xOffset, xOffsetStep); }, timeToWait); } } - private void processLocalColorsInternal() { + private void processLocalColorsInternal(float xOffset, float xOffsetStep) { // implemented by the wallpaper if (supportsLocalColorExtraction()) return; - assertBackgroundThread(); - float xOffset; - float xOffsetStep; - float wallpaperDimAmount; - synchronized (mLock) { - xOffset = mPendingXOffset; - xOffsetStep = mPendingXOffsetStep; - wallpaperDimAmount = mWallpaperDimAmount; - } - if (DEBUG) { Log.d(TAG, "processLocalColors " + xOffset + " of step " + xOffsetStep); @@ -1698,7 +1680,7 @@ public abstract class WallpaperService extends Service { xPage = mWindowPages.length - 1; } current = mWindowPages[xPage]; - updatePage(current, xPage, xPages, wallpaperDimAmount); + updatePage(current, xPage, xPages, finalXOffsetStep); Trace.endSection(); } @@ -1718,23 +1700,16 @@ public abstract class WallpaperService extends Service { } } - /** - * Must be called with the surface lock held. - * Must not be called if the surface is not valid. - * Will unlock the surface when done using it. - */ void updatePage(EngineWindowPage currentPage, int pageIndx, int numPages, - float wallpaperDimAmount) { - - assertBackgroundThread(); - + float xOffsetStep) { // in case the clock is zero, we start with negative time long current = SystemClock.elapsedRealtime() - DEFAULT_UPDATE_SCREENSHOT_DURATION; long lapsed = current - currentPage.getLastUpdateTime(); // Always update the page when the last update time is <= 0 // This is important especially when the device first boots - if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) return; - + if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) { + return; + } Surface surface = mSurfaceHolder.getSurface(); if (!surface.isValid()) return; boolean widthIsLarger = mSurfaceSize.x > mSurfaceSize.y; @@ -1750,42 +1725,33 @@ public abstract class WallpaperService extends Service { Bitmap screenShot = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); final Bitmap finalScreenShot = screenShot; - final String pixelCopySectionName = "WallpaperService#pixelCopy"; - final int pixelCopyCount = mPixelCopyCount++; - Trace.beginAsyncSection(pixelCopySectionName, pixelCopyCount); - try { - PixelCopy.request(surface, screenShot, (res) -> { - Trace.endAsyncSection(pixelCopySectionName, pixelCopyCount); - if (DEBUG) Log.d(TAG, "result of pixel copy is " + res); - if (res != PixelCopy.SUCCESS) { - Bitmap lastBitmap = currentPage.getBitmap(); - // assign the last bitmap taken for now - currentPage.setBitmap(mLastScreenshot); - Bitmap lastScreenshot = mLastScreenshot; - if (lastScreenshot != null && !lastScreenshot.isRecycled() - && !Objects.equals(lastBitmap, lastScreenshot)) { - updatePageColors(currentPage, pageIndx, numPages, wallpaperDimAmount); - } - } else { - mLastScreenshot = finalScreenShot; - // going to hold this lock for a while - currentPage.setBitmap(finalScreenShot); - currentPage.setLastUpdateTime(current); - updatePageColors(currentPage, pageIndx, numPages, wallpaperDimAmount); + Trace.beginSection("WallpaperService#pixelCopy"); + PixelCopy.request(surface, screenShot, (res) -> { + Trace.endSection(); + if (DEBUG) Log.d(TAG, "result of pixel copy is " + res); + if (res != PixelCopy.SUCCESS) { + Bitmap lastBitmap = currentPage.getBitmap(); + // assign the last bitmap taken for now + currentPage.setBitmap(mLastScreenshot); + Bitmap lastScreenshot = mLastScreenshot; + if (lastScreenshot != null && !lastScreenshot.isRecycled() + && !Objects.equals(lastBitmap, lastScreenshot)) { + updatePageColors(currentPage, pageIndx, numPages, xOffsetStep); } - }, mBackgroundHandler); - } catch (IllegalArgumentException e) { - // this can potentially happen if the surface is invalidated right between the - // surface.isValid() check and the PixelCopy operation. - // in this case, stop: we'll compute colors on the next processLocalColors call. - Log.i(TAG, "Cancelling processLocalColors: exception caught during PixelCopy"); - } + } else { + mLastScreenshot = finalScreenShot; + // going to hold this lock for a while + currentPage.setBitmap(finalScreenShot); + currentPage.setLastUpdateTime(current); + updatePageColors(currentPage, pageIndx, numPages, xOffsetStep); + } + }, mHandler); + } // locked by the passed page - private void updatePageColors( - EngineWindowPage page, int pageIndx, int numPages, float wallpaperDimAmount) { + private void updatePageColors(EngineWindowPage page, int pageIndx, int numPages, + float xOffsetStep) { if (page.getBitmap() == null) return; - assertBackgroundThread(); Trace.beginSection("WallpaperService#updatePageColors"); if (DEBUG) { Log.d(TAG, "updatePageColorsLocked for page " + pageIndx + " with areas " @@ -1807,7 +1773,7 @@ public abstract class WallpaperService extends Service { Log.e(TAG, "Error creating page local color bitmap", e); continue; } - WallpaperColors color = WallpaperColors.fromBitmap(target, wallpaperDimAmount); + WallpaperColors color = WallpaperColors.fromBitmap(target, mWallpaperDimAmount); target.recycle(); WallpaperColors currentColor = page.getColors(area); @@ -1824,26 +1790,17 @@ public abstract class WallpaperService extends Service { + " local color callback for area" + area + " for page " + pageIndx + " of " + numPages); } - mHandler.post(() -> { - try { - mConnection.onLocalWallpaperColorsChanged(area, color, - mDisplayContext.getDisplayId()); - } catch (RemoteException e) { - Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e); - } - }); + try { + mConnection.onLocalWallpaperColorsChanged(area, color, + mDisplayContext.getDisplayId()); + } catch (RemoteException e) { + Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e); + } } } Trace.endSection(); } - private void assertBackgroundThread() { - if (!mBackgroundHandler.getLooper().isCurrentThread()) { - throw new IllegalStateException( - "ProcessLocalColors should be called from the background thread"); - } - } - private RectF generateSubRect(RectF in, int pageInx, int numPages) { float minLeft = (float) (pageInx) / (float) (numPages); float maxRight = (float) (pageInx + 1) / (float) (numPages); @@ -1868,6 +1825,7 @@ public abstract class WallpaperService extends Service { if (supportsLocalColorExtraction()) return; if (!mResetWindowPages) return; mResetWindowPages = false; + mLastWindowPage = -1; for (int i = 0; i < mWindowPages.length; i++) { mWindowPages[i].setLastUpdateTime(0L); } @@ -1893,10 +1851,12 @@ public abstract class WallpaperService extends Service { if (DEBUG) { Log.d(TAG, "addLocalColorsAreas adding local color areas " + regions); } - mBackgroundHandler.post(() -> { + mHandler.post(() -> { mLocalColorsToAdd.addAll(regions); - processLocalColors(); + processLocalColors(mPendingXOffset, mPendingYOffset); }); + + } /** @@ -1906,7 +1866,7 @@ public abstract class WallpaperService extends Service { */ public void removeLocalColorsAreas(@NonNull List<RectF> regions) { if (supportsLocalColorExtraction()) return; - mBackgroundHandler.post(() -> { + mHandler.post(() -> { float step = mPendingXOffsetStep; mLocalColorsToAdd.removeAll(regions); mLocalColorAreas.removeAll(regions); @@ -2537,9 +2497,6 @@ public abstract class WallpaperService extends Service { @Override public void onCreate() { Trace.beginSection("WPMS.onCreate"); - mBackgroundThread = new HandlerThread("DefaultWallpaperLocalColorExtractor"); - mBackgroundThread.start(); - mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); super.onCreate(); Trace.endSection(); } @@ -2552,7 +2509,6 @@ public abstract class WallpaperService extends Service { mActiveEngines.get(i).detach(); } mActiveEngines.clear(); - mBackgroundThread.quitSafely(); Trace.endSection(); } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 3a0e09d1fc77..6fed26c4a81d 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -81,7 +81,6 @@ import android.telephony.ServiceState.RegState; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.text.TextUtils; -import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; @@ -202,7 +201,6 @@ public class BatteryStatsImpl extends BatteryStats { public static final int RESET_REASON_ADB_COMMAND = 2; public static final int RESET_REASON_FULL_CHARGE = 3; public static final int RESET_REASON_MEASURED_ENERGY_BUCKETS_CHANGE = 4; - public static final int RESET_REASON_PLUGGED_IN_FOR_LONG_DURATION = 5; protected Clock mClock; @@ -389,89 +387,6 @@ public class BatteryStatsImpl extends BatteryStats { } } - /** Provide BatteryStatsImpl configuration choices */ - public static class BatteryStatsConfig { - static final int RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG = 1 << 0; - static final int RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG = 1 << 1; - - private final int mFlags; - - private BatteryStatsConfig(Builder builder) { - int flags = 0; - if (builder.mResetOnUnplugHighBatteryLevel) { - flags |= RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG; - } - if (builder.mResetOnUnplugAfterSignificantCharge) { - flags |= RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG; - } - mFlags = flags; - } - - /** - * Returns whether a BatteryStats reset should occur on unplug when the battery level is - * high. - */ - boolean shouldResetOnUnplugHighBatteryLevel() { - return (mFlags & RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG) - == RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG; - } - - /** - * Returns whether a BatteryStats reset should occur on unplug if the battery charge a - * significant amount since it has been plugged in. - */ - boolean shouldResetOnUnplugAfterSignificantCharge() { - return (mFlags & RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG) - == RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG; - } - - /** - * Builder for BatteryStatsConfig - */ - public static class Builder { - private boolean mResetOnUnplugHighBatteryLevel; - private boolean mResetOnUnplugAfterSignificantCharge; - public Builder() { - mResetOnUnplugHighBatteryLevel = true; - mResetOnUnplugAfterSignificantCharge = true; - } - - /** - * Build the BatteryStatsConfig. - */ - public BatteryStatsConfig build() { - return new BatteryStatsConfig(this); - } - - /** - * Set whether a BatteryStats reset should occur on unplug when the battery level is - * high. - */ - public Builder setResetOnUnplugHighBatteryLevel(boolean reset) { - mResetOnUnplugHighBatteryLevel = reset; - return this; - } - - /** - * Set whether a BatteryStats reset should occur on unplug if the battery charge a - * significant amount since it has been plugged in. - */ - public Builder setResetOnUnplugAfterSignificantCharge(boolean reset) { - mResetOnUnplugAfterSignificantCharge = reset; - return this; - } - } - - } - - /** Handles calls to AlarmManager */ - public interface AlarmInterface { - /** Schedule an RTC alarm */ - void schedule(long rtcTimeMs, long windowLengthMs); - /** Cancel the previously scheduled alarm */ - void cancel(); - } - private final PlatformIdleStateCallback mPlatformIdleStateCallback; private final Runnable mDeferSetCharging = new Runnable() { @@ -802,7 +717,6 @@ public class BatteryStatsImpl extends BatteryStats { protected boolean mHaveBatteryLevel = false; protected boolean mRecordingHistory = false; int mNumHistoryItems; - private long mBatteryPluggedInRealTimeMs = 0; private static final int HISTORY_TAG_INDEX_LIMIT = 0x7ffe; private static final int MAX_HISTORY_TAG_STRING_LENGTH = 1024; @@ -1545,13 +1459,6 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") protected final Constants mConstants; - @VisibleForTesting - @GuardedBy("this") - protected BatteryStatsConfig mBatteryStatsConfig = new BatteryStatsConfig.Builder().build(); - - @VisibleForTesting - protected AlarmInterface mLongPlugInAlarmInterface = null; - /* * Holds a SamplingTimer associated with each Resource Power Manager state and voter, * recording their times when on-battery (regardless of screen state). @@ -1718,13 +1625,12 @@ public class BatteryStatsImpl extends BatteryStats { public BatteryStatsImpl(Clock clock, File historyDirectory) { init(clock); mStartClockTimeMs = clock.currentTimeMillis(); + mCheckinFile = null; mDailyFile = null; if (historyDirectory == null) { - mCheckinFile = null; mStatsFile = null; mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer); } else { - mCheckinFile = new AtomicFile(new File(historyDirectory, "batterystats-checkin.bin")); mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin")); mBatteryStatsHistory = new BatteryStatsHistory(this, historyDirectory, mHistoryBuffer); } @@ -12642,27 +12548,6 @@ public class BatteryStatsImpl extends BatteryStats { } /** - * Injects BatteryStatsConfig - */ - public void setBatteryStatsConfig(BatteryStatsConfig config) { - synchronized (this) { - mBatteryStatsConfig = config; - } - } - - /** - * Injects a LongPlugInAlarmHandler - */ - public void setLongPlugInAlarmInterface(AlarmInterface longPlugInAlarmInterface) { - synchronized (this) { - mLongPlugInAlarmInterface = longPlugInAlarmInterface; - if (!mOnBattery) { - scheduleNextResetWhilePluggedInCheck(); - } - } - } - - /** * Starts tracking CPU time-in-state for threads of the system server process, * keeping a separate account of threads receiving incoming binder calls. */ @@ -13134,12 +13019,12 @@ public class BatteryStatsImpl extends BatteryStats { } @GuardedBy("this") - public void resetAllStatsAndHistoryLocked(int reason) { + public void resetAllStatsCmdLocked() { final long mSecUptime = mClock.uptimeMillis(); long uptimeUs = mSecUptime * 1000; long mSecRealtime = mClock.elapsedRealtime(); long realtimeUs = mSecRealtime * 1000; - resetAllStatsLocked(mSecUptime, mSecRealtime, reason); + resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_ADB_COMMAND); mDischargeStartLevel = mHistoryCur.batteryLevel; pullPendingStateUpdatesLocked(); addHistoryRecordLocked(mSecRealtime, mSecUptime); @@ -15613,73 +15498,6 @@ public class BatteryStatsImpl extends BatteryStats { } /** - * Might reset battery stats if conditions are met. Assumed the device is currently plugged in. - */ - @GuardedBy("this") - public void maybeResetWhilePluggedInLocked() { - final long elapsedRealtimeMs = mClock.elapsedRealtime(); - if (shouldResetWhilePluggedInLocked(elapsedRealtimeMs)) { - Slog.i(TAG, - "Resetting due to long plug in duration. elapsed time = " + elapsedRealtimeMs - + " ms, last plug in time = " + mBatteryPluggedInRealTimeMs - + " ms, last reset time = " + mRealtimeStartUs / 1000); - resetAllStatsAndHistoryLocked(RESET_REASON_PLUGGED_IN_FOR_LONG_DURATION); - } - - scheduleNextResetWhilePluggedInCheck(); - } - - @GuardedBy("this") - private void scheduleNextResetWhilePluggedInCheck() { - if (mLongPlugInAlarmInterface != null) { - final long timeoutMs = mClock.currentTimeMillis() - + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS - * DateUtils.HOUR_IN_MILLIS; - Calendar nextAlarm = Calendar.getInstance(); - nextAlarm.setTimeInMillis(timeoutMs); - - // Find the 2 AM the same day as the end of the minimum duration. - // This logic does not handle a Daylight Savings transition, or a timezone change - // while the alarm has been set. The need to reset after a long period while plugged - // in is not strict enough to warrant a well architected out solution. - nextAlarm.set(Calendar.MILLISECOND, 0); - nextAlarm.set(Calendar.SECOND, 0); - nextAlarm.set(Calendar.MINUTE, 0); - nextAlarm.set(Calendar.HOUR_OF_DAY, 2); - long nextTimeMs = nextAlarm.getTimeInMillis(); - if (nextTimeMs < timeoutMs) { - // The 2AM on the day of the timeout, move on the next day. - nextTimeMs += DateUtils.DAY_IN_MILLIS; - } - mLongPlugInAlarmInterface.schedule(nextTimeMs, DateUtils.HOUR_IN_MILLIS); - } - } - - - @GuardedBy("this") - private boolean shouldResetWhilePluggedInLocked(long elapsedRealtimeMs) { - if (mNoAutoReset) return false; - if (!mSystemReady) return false; - - final long pluggedInThresholdMs = mBatteryPluggedInRealTimeMs - + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS - * DateUtils.HOUR_IN_MILLIS; - if (elapsedRealtimeMs >= pluggedInThresholdMs) { - // The device has been plugged in for a long time. - final long resetThresholdMs = mRealtimeStartUs / 1000 - + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS - * DateUtils.HOUR_IN_MILLIS; - if (elapsedRealtimeMs >= resetThresholdMs) { - // And it has been a long time since the last reset. - return true; - } - } - - return false; - } - - - /** * Notifies BatteryStatsImpl that the system server is ready. */ public void onSystemReady() { @@ -15687,32 +15505,6 @@ public class BatteryStatsImpl extends BatteryStats { } @GuardedBy("this") - private boolean shouldResetOnUnplugLocked(int batteryStatus, int batteryLevel) { - if (mNoAutoReset) return false; - if (!mSystemReady) return false; - if (mBatteryStatsConfig.shouldResetOnUnplugHighBatteryLevel()) { - // Allow resetting due to currently being at high battery level - if (batteryStatus == BatteryManager.BATTERY_STATUS_FULL) return true; - if (batteryLevel >= 90) return true; - } - if (mBatteryStatsConfig.shouldResetOnUnplugAfterSignificantCharge()) { - // Allow resetting after a significant charge (from a very low level to a now very - // high level). - if (mDischargePlugLevel < 20 && batteryLevel >= 80) return true; - } - if (getHighDischargeAmountSinceCharge() >= 200) { - // Reset the stats if battery got partially charged and discharged repeatedly without - // ever reaching the full charge. - // This reset is done in order to prevent stats sessions from going on forever. - // Exceedingly long battery sessions would lead to an overflow of - // data structures such as mWakeupReasonStats. - return true; - } - - return false; - } - - @GuardedBy("this") protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery, final int oldStatus, final int level, final int chargeUah) { boolean doWrite = false; @@ -15724,10 +15516,23 @@ public class BatteryStatsImpl extends BatteryStats { final long realtimeUs = mSecRealtime * 1000; final int screenState = mScreenState; if (onBattery) { + // We will reset our status if we are unplugging after the + // battery was last full, or the level is at 100, or + // we have gone through a significant charge (from a very low + // level to a now very high level). + // Also, we will reset the stats if battery got partially charged + // and discharged repeatedly without ever reaching the full charge. + // This reset is done in order to prevent stats sessions from going on forever. + // Exceedingly long battery sessions would lead to an overflow of + // data structures such as mWakeupReasonStats. boolean reset = false; - if (shouldResetOnUnplugLocked(oldStatus, level)) { + if (!mNoAutoReset && mSystemReady + && (oldStatus == BatteryManager.BATTERY_STATUS_FULL + || level >= 90 + || (mDischargeCurrentLevel < 20 && level >= 80) + || getHighDischargeAmountSinceCharge() >= 200)) { Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus - + " dischargeLevel=" + mDischargePlugLevel + + " dischargeLevel=" + mDischargeCurrentLevel + " lowAmount=" + getLowDischargeAmountSinceCharge() + " highAmount=" + getHighDischargeAmountSinceCharge()); // Before we write, collect a snapshot of the final aggregated @@ -15784,9 +15589,6 @@ public class BatteryStatsImpl extends BatteryStats { mInitStepMode = mCurStepMode; mModStepMode = 0; pullPendingStateUpdatesLocked(); - if (mLongPlugInAlarmInterface != null) { - mLongPlugInAlarmInterface.cancel(); - } mHistoryCur.batteryLevel = (byte)level; mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: " @@ -15818,7 +15620,6 @@ public class BatteryStatsImpl extends BatteryStats { mLastChargingStateLevel = level; mOnBattery = mOnBatteryInternal = false; pullPendingStateUpdatesLocked(); - mBatteryPluggedInRealTimeMs = mSecRealtime; mHistoryCur.batteryLevel = (byte)level; mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: " @@ -15836,7 +15637,6 @@ public class BatteryStatsImpl extends BatteryStats { mMaxChargeStepLevel = level; mInitStepMode = mCurStepMode; mModStepMode = 0; - scheduleNextResetWhilePluggedInCheck(); } if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) { if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) { @@ -16851,8 +16651,6 @@ public class BatteryStatsImpl extends BatteryStats { public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb"; public static final String KEY_BATTERY_CHARGED_DELAY_MS = "battery_charged_delay_ms"; - public static final String KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = - "reset_while_plugged_in_minimum_duration_hours"; private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true; private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000; @@ -16865,8 +16663,6 @@ public class BatteryStatsImpl extends BatteryStats { private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64; private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/ private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */ - // Little less than 2 days - private static final int DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = 47; public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME; /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an @@ -16882,8 +16678,6 @@ public class BatteryStatsImpl extends BatteryStats { public int MAX_HISTORY_FILES; public int MAX_HISTORY_BUFFER; /*Bytes*/ public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS; - public int RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = - DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS; private ContentResolver mResolver; private final KeyValueListParser mParser = new KeyValueListParser(','); @@ -16960,11 +16754,6 @@ public class BatteryStatsImpl extends BatteryStats { DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB : DEFAULT_MAX_HISTORY_BUFFER_KB) * 1024; - - RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = mParser.getInt( - KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS, - DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS); - updateBatteryChargedDelayMsLocked(); } } @@ -17019,8 +16808,6 @@ public class BatteryStatsImpl extends BatteryStats { pw.println(MAX_HISTORY_BUFFER/1024); pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("="); pw.println(BATTERY_CHARGED_DELAY_MS); - pw.print(KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS); pw.print("="); - pw.println(RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS); } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 31903e25f8fd..0e95e30a99b8 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3154,7 +3154,11 @@ android:protectionLevel="normal" /> <!-- Allows an application to call - {@link android.app.ActivityManager#killBackgroundProcesses}. + {@link android.app.ActivityManager#killBackgroundProcesses}. + + <p class="note">Third party applications can only use this API to kill their own + processes.</p> + <p>Protection level: normal --> <permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 58c8b29dfad6..dafa0ad7989f 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -6092,9 +6092,4 @@ <!-- Whether to show weather on the lock screen by default. --> <bool name="config_lockscreenWeatherEnabledByDefault">false</bool> - - <!-- Whether to reset Battery Stats on unplug when the battery level is high. --> - <bool name="config_batteryStatsResetOnUnplugHighBatteryLevel">true</bool> - <!-- Whether to reset Battery Stats on unplug if the battery was significantly charged --> - <bool name="config_batteryStatsResetOnUnplugAfterSignificantCharge">true</bool> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 8addca27a7bb..591ba5feeee9 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4903,7 +4903,4 @@ <!-- Whether to show weather on the lockscreen by default. --> <java-symbol type="bool" name="config_lockscreenWeatherEnabledByDefault" /> - - <java-symbol type="bool" name="config_batteryStatsResetOnUnplugHighBatteryLevel" /> - <java-symbol type="bool" name="config_batteryStatsResetOnUnplugAfterSignificantCharge" /> </resources> diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsResetTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsResetTest.java deleted file mode 100644 index 9c2d332a7c70..000000000000 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsResetTest.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (C) 2023 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.os; - - -import static com.google.common.truth.Truth.assertThat; - -import android.content.Context; -import android.os.BatteryManager; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class BatteryStatsResetTest { - - private static final int BATTERY_NOMINAL_VOLTAGE_MV = 3700; - private static final int BATTERY_CAPACITY_UAH = 4_000_000; - private static final int BATTERY_CHARGE_RATE_SECONDS_PER_LEVEL = 100; - - private MockClock mMockClock; - private MockBatteryStatsImpl mBatteryStatsImpl; - - - /** - * Battery status. Must be one of the following: - * {@link BatteryManager#BATTERY_STATUS_UNKNOWN} - * {@link BatteryManager#BATTERY_STATUS_CHARGING} - * {@link BatteryManager#BATTERY_STATUS_DISCHARGING} - * {@link BatteryManager#BATTERY_STATUS_NOT_CHARGING} - * {@link BatteryManager#BATTERY_STATUS_FULL} - */ - private int mBatteryStatus; - /** - * Battery health. Must be one of the following: - * {@link BatteryManager#BATTERY_HEALTH_UNKNOWN} - * {@link BatteryManager#BATTERY_HEALTH_GOOD} - * {@link BatteryManager#BATTERY_HEALTH_OVERHEAT} - * {@link BatteryManager#BATTERY_HEALTH_DEAD} - * {@link BatteryManager#BATTERY_HEALTH_OVER_VOLTAGE} - * {@link BatteryManager#BATTERY_HEALTH_UNSPECIFIED_FAILURE} - * {@link BatteryManager#BATTERY_HEALTH_COLD} - */ - private int mBatteryHealth; - /** - * Battery plug type. Can be the union of any number of the following flags: - * {@link BatteryManager#BATTERY_PLUGGED_AC} - * {@link BatteryManager#BATTERY_PLUGGED_USB} - * {@link BatteryManager#BATTERY_PLUGGED_WIRELESS} - * {@link BatteryManager#BATTERY_PLUGGED_DOCK} - * - * Zero means the device is unplugged. - */ - private int mBatteryPlugType; - private int mBatteryLevel; - private int mBatteryTemp; - private int mBatteryVoltageMv; - private int mBatteryChargeUah; - private int mBatteryChargeFullUah; - private long mBatteryChargeTimeToFullSeconds; - - @Before - public void setUp() { - final Context context = InstrumentationRegistry.getContext(); - - mMockClock = new MockClock(); - mBatteryStatsImpl = new MockBatteryStatsImpl(mMockClock, context.getFilesDir()); - mBatteryStatsImpl.onSystemReady(); - - - // Set up the battery state. Start off with a fully charged plugged in battery. - mBatteryStatus = BatteryManager.BATTERY_STATUS_FULL; - mBatteryHealth = BatteryManager.BATTERY_HEALTH_GOOD; - mBatteryPlugType = BatteryManager.BATTERY_PLUGGED_USB; - mBatteryLevel = 100; - mBatteryTemp = 70; // Arbitrary reasonable temperature. - mBatteryVoltageMv = BATTERY_NOMINAL_VOLTAGE_MV; - mBatteryChargeUah = BATTERY_CAPACITY_UAH; - mBatteryChargeFullUah = BATTERY_CAPACITY_UAH; - mBatteryChargeTimeToFullSeconds = 0; - } - - @Test - public void testResetOnUnplug_highBatteryLevel() { - mBatteryStatsImpl.setBatteryStatsConfig( - new BatteryStatsImpl.BatteryStatsConfig.Builder() - .setResetOnUnplugHighBatteryLevel(true) - .build()); - - long expectedResetTimeUs = 0; - - unplugBattery(); - dischargeToLevel(60); - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - chargeToLevel(80); - unplugBattery(); - // Reset should not occur until battery level above 90. - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - chargeToLevel(95); - // Reset should not occur until unplug. - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - unplugBattery(); - // Reset should occur on unplug now that battery level is high (>=90) - expectedResetTimeUs = mMockClock.elapsedRealtime() * 1000; - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // disable high battery level reset on unplug. - mBatteryStatsImpl.setBatteryStatsConfig( - new BatteryStatsImpl.BatteryStatsConfig.Builder() - .setResetOnUnplugHighBatteryLevel(false) - .build()); - - dischargeToLevel(60); - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - chargeToLevel(95); - unplugBattery(); - // Reset should not occur since the high battery level logic has been disabled. - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - } - - @Test - public void testResetOnUnplug_significantCharge() { - mBatteryStatsImpl.setBatteryStatsConfig( - new BatteryStatsImpl.BatteryStatsConfig.Builder() - .setResetOnUnplugAfterSignificantCharge(true) - .build()); - long expectedResetTimeUs = 0; - - unplugBattery(); - // Battery level dropped below 20%. - dischargeToLevel(15); - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - chargeToLevel(50); - unplugBattery(); - // Reset should not occur until battery level above 80 - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - chargeToLevel(85); - unplugBattery(); - // Reset should not occur because the charge session did not go from 20% to 80% - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // Battery level dropped below 20%. - dischargeToLevel(15); - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - chargeToLevel(85); - unplugBattery(); - // Reset should occur after significant charge amount. - expectedResetTimeUs = mMockClock.elapsedRealtime() * 1000; - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // disable reset on unplug after significant charge. - mBatteryStatsImpl.setBatteryStatsConfig( - new BatteryStatsImpl.BatteryStatsConfig.Builder() - .setResetOnUnplugAfterSignificantCharge(false) - .build()); - - // Battery level dropped below 20%. - dischargeToLevel(15); - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - chargeToLevel(85); - unplugBattery(); - // Reset should not occur after significant charge amount. - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - } - - @Test - public void testResetOnUnplug_manyPartialCharges() { - long expectedResetTimeUs = 0; - - unplugBattery(); - // Cumulative battery discharged: 60%. - dischargeToLevel(40); - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - chargeToLevel(80); - unplugBattery(); - // Reset should not occur - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // Cumulative battery discharged: 100%. - dischargeToLevel(40); - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - chargeToLevel(80); - unplugBattery(); - // Reset should not occur - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // Cumulative battery discharged: 140%. - dischargeToLevel(40); - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - chargeToLevel(80); - unplugBattery(); - // Reset should not occur - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // Cumulative battery discharged: 180%. - dischargeToLevel(40); - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - chargeToLevel(80); - unplugBattery(); - // Reset should not occur - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // Cumulative battery discharged: 220%. - dischargeToLevel(40); - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - chargeToLevel(80); - unplugBattery(); - // Should reset after >200% of cumulative battery discharge - expectedResetTimeUs = mMockClock.elapsedRealtime() * 1000; - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - } - - @Test - public void testResetWhilePluggedIn_longPlugIn() { - // disable high battery level reset on unplug. - mBatteryStatsImpl.setBatteryStatsConfig( - new BatteryStatsImpl.BatteryStatsConfig.Builder() - .setResetOnUnplugHighBatteryLevel(false) - .setResetOnUnplugAfterSignificantCharge(false) - .build()); - long expectedResetTimeUs = 0; - - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - mBatteryStatsImpl.maybeResetWhilePluggedInLocked(); - // Reset should not occur - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // Increment time a day - incTimeMs(24L * 60L * 60L * 1000L); - mBatteryStatsImpl.maybeResetWhilePluggedInLocked(); - // Reset should still not occur - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // Increment time a day - incTimeMs(24L * 60L * 60L * 1000L); - mBatteryStatsImpl.maybeResetWhilePluggedInLocked(); - // Reset 47 hour threshold crossed, reset should occur. - expectedResetTimeUs = mMockClock.elapsedRealtime() * 1000; - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // Increment time a day - incTimeMs(24L * 60L * 60L * 1000L); - mBatteryStatsImpl.maybeResetWhilePluggedInLocked(); - // Reset should not occur - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // Increment time a day - incTimeMs(24L * 60L * 60L * 1000L); - mBatteryStatsImpl.maybeResetWhilePluggedInLocked(); - // Reset another 47 hour threshold crossed, reset should occur. - expectedResetTimeUs = mMockClock.elapsedRealtime() * 1000; - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // Increment time a day - incTimeMs(24L * 60L * 60L * 1000L); - mBatteryStatsImpl.maybeResetWhilePluggedInLocked(); - // Reset should not occur - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - unplugBattery(); - plugBattery(BatteryManager.BATTERY_PLUGGED_USB); - - // Increment time a day - incTimeMs(24L * 60L * 60L * 1000L); - mBatteryStatsImpl.maybeResetWhilePluggedInLocked(); - // Reset should not occur, since unplug occurred recently. - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - - // Increment time a day - incTimeMs(24L * 60L * 60L * 1000L); - mBatteryStatsImpl.maybeResetWhilePluggedInLocked(); - // Reset another 47 hour threshold crossed, reset should occur. - expectedResetTimeUs = mMockClock.elapsedRealtime() * 1000; - assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs); - } - - private void dischargeToLevel(int targetLevel) { - mBatteryStatus = BatteryManager.BATTERY_STATUS_DISCHARGING; - for (int level = mBatteryLevel - 1; level >= targetLevel; level--) { - prepareBatteryLevel(level); - incTimeMs(5000); // Arbitrary discharge rate. - updateBatteryState(); - } - } - - private void chargeToLevel(int targetLevel) { - mBatteryStatus = BatteryManager.BATTERY_STATUS_CHARGING; - for (int level = mBatteryLevel + 1; level <= targetLevel; level++) { - if (level >= 100) mBatteryStatus = BatteryManager.BATTERY_STATUS_FULL; - prepareBatteryLevel(level); - incTimeMs(BATTERY_CHARGE_RATE_SECONDS_PER_LEVEL * 1000); - updateBatteryState(); - } - } - - private void unplugBattery() { - mBatteryPlugType = 0; - updateBatteryState(); - } - - private void plugBattery(int type) { - mBatteryPlugType |= type; - updateBatteryState(); - } - - private void prepareBatteryLevel(int level) { - mBatteryLevel = level; - mBatteryChargeUah = mBatteryLevel * mBatteryChargeFullUah / 100; - mBatteryChargeTimeToFullSeconds = - (100 - mBatteryLevel) * BATTERY_CHARGE_RATE_SECONDS_PER_LEVEL; - } - - private void incTimeMs(long milliseconds) { - mMockClock.realtime += milliseconds; - mMockClock.uptime += milliseconds / 2; // Arbitrary slower uptime accumulation - mMockClock.currentTime += milliseconds; - } - - private void updateBatteryState() { - mBatteryStatsImpl.setBatteryStateLocked(mBatteryStatus, mBatteryHealth, mBatteryPlugType, - mBatteryLevel, mBatteryTemp, mBatteryVoltageMv, mBatteryChargeUah, - mBatteryChargeFullUah, mBatteryChargeTimeToFullSeconds, - mMockClock.elapsedRealtime(), mMockClock.uptimeMillis(), - mMockClock.currentTimeMillis()); - } -} - diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java index ae2d1afe0320..274286135174 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java @@ -342,7 +342,7 @@ public class BatteryUsageStatsProviderTest { Context context = InstrumentationRegistry.getContext(); BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats(); mStatsRule.setCurrentTime(5 * MINUTE_IN_MS); - batteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND); + batteryStats.resetAllStatsCmdLocked(); BatteryUsageStatsStore batteryUsageStatsStore = new BatteryUsageStatsStore(context, batteryStats, new File(context.getCacheDir(), "BatteryUsageStatsProviderTest"), @@ -357,14 +357,14 @@ public class BatteryUsageStatsProviderTest { batteryStats.noteFlashlightOffLocked(APP_UID, 20 * MINUTE_IN_MS, 20 * MINUTE_IN_MS); mStatsRule.setCurrentTime(25 * MINUTE_IN_MS); - batteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND); + batteryStats.resetAllStatsCmdLocked(); batteryStats.noteFlashlightOnLocked(APP_UID, 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS); batteryStats.noteFlashlightOffLocked(APP_UID, 50 * MINUTE_IN_MS, 50 * MINUTE_IN_MS); mStatsRule.setCurrentTime(55 * MINUTE_IN_MS); - batteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND); + batteryStats.resetAllStatsCmdLocked(); // This section should be ignored because the timestamp is out or range batteryStats.noteFlashlightOnLocked(APP_UID, @@ -372,7 +372,7 @@ public class BatteryUsageStatsProviderTest { batteryStats.noteFlashlightOffLocked(APP_UID, 70 * MINUTE_IN_MS, 70 * MINUTE_IN_MS); mStatsRule.setCurrentTime(75 * MINUTE_IN_MS); - batteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND); + batteryStats.resetAllStatsCmdLocked(); // This section should be ignored because it represents the current stats session batteryStats.noteFlashlightOnLocked(APP_UID, diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsStoreTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsStoreTest.java index 11b9047fab7f..c9729fab3b5e 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsStoreTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsStoreTest.java @@ -84,7 +84,7 @@ public class BatteryUsageStatsStoreTest { mMockClock.realtime = 1_000_000; mMockClock.uptime = 1_000_000; - mBatteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND); + mBatteryStats.resetAllStatsCmdLocked(); final long[] timestamps = mBatteryUsageStatsStore.listBatteryUsageStatsTimestamps(); assertThat(timestamps).hasLength(1); @@ -114,7 +114,7 @@ public class BatteryUsageStatsStoreTest { final int numberOfSnapshots = (int) (MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES / snapshotFileSize); for (int i = 0; i < numberOfSnapshots + 2; i++) { - mBatteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND); + mBatteryStats.resetAllStatsCmdLocked(); mMockClock.realtime += 10_000_000; mMockClock.uptime += 10_000_000; @@ -141,7 +141,7 @@ public class BatteryUsageStatsStoreTest { mMockClock.currentTime += 10_000_000; prepareBatteryStats(); - mBatteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND); + mBatteryStats.resetAllStatsCmdLocked(); } assertThat(getDirectorySize(mStoreDirectory)).isNotEqualTo(0); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index a6733843d4c3..7d3e7ca671e5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -204,7 +204,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // and exit, since exit itself can trigger a number of changes that update the stages. private boolean mShouldUpdateRecents; private boolean mExitSplitScreenOnHide; - private boolean mIsSplitEntering; + private boolean mIsDividerRemoteAnimating; private boolean mIsDropEntering; private boolean mIsExiting; @@ -881,7 +881,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Set false to avoid record new bounds with old task still on top; mShouldUpdateRecents = false; - mIsSplitEntering = true; + mIsDividerRemoteAnimating = true; if (mSplitRequest == null) { mSplitRequest = new SplitRequest(mainTaskId, mainPendingIntent != null ? mainPendingIntent.getIntent() : null, @@ -974,7 +974,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } private void onRemoteAnimationFinishedOrCancelled(WindowContainerTransaction evictWct) { - mIsSplitEntering = false; + mIsDividerRemoteAnimating = false; mShouldUpdateRecents = true; mSplitRequest = null; // If any stage has no child after animation finished, it means that split will display @@ -1240,7 +1240,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } }); mShouldUpdateRecents = false; - mIsSplitEntering = false; + mIsDividerRemoteAnimating = false; mSplitLayout.getInvisibleBounds(mTempRect1); if (childrenToTop == null || childrenToTop.getTopVisibleChildTaskId() == INVALID_TASK_ID) { @@ -1573,7 +1573,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, && !ENABLE_SHELL_TRANSITIONS) { // Clear the divider remote animating flag as the divider will be re-rendered to apply // the new rotation config. - mIsSplitEntering = false; + mIsDividerRemoteAnimating = false; mSplitLayout.update(null /* t */); onLayoutSizeChanged(mSplitLayout); } @@ -1623,9 +1623,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } void onChildTaskAppeared(StageListenerImpl stageListener, int taskId) { + // Handle entering split screen while there is a split pair running in the background. if (stageListener == mSideStageListener && !isSplitScreenVisible() && isSplitActive() - && !mIsSplitEntering) { - // Handle entring split case here if split already running background. + && mSplitRequest == null) { if (mIsDropEntering) { mSplitLayout.resetDividerPosition(); } else { @@ -1717,7 +1717,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mDividerVisible = visible; sendSplitVisibilityChanged(); - if (mIsSplitEntering) { + if (mIsDividerRemoteAnimating) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, " Skip animating divider bar due to it's remote animating."); return; @@ -1737,7 +1737,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, " Skip animating divider bar due to divider leash not ready."); return; } - if (mIsSplitEntering) { + if (mIsDividerRemoteAnimating) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, " Skip animating divider bar due to it's remote animating."); return; @@ -1805,7 +1805,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitLayout.flingDividerToDismiss( mSideStagePosition != SPLIT_POSITION_BOTTOM_OR_RIGHT, EXIT_REASON_APP_FINISHED); - } else if (!isSplitScreenVisible() && !mIsSplitEntering) { + } else if (!isSplitScreenVisible() && mSplitRequest == null) { + // Dismiss split screen in the background once any sides of the split become empty. exitSplitScreen(null /* childrenToTop */, EXIT_REASON_APP_FINISHED); } } else if (isSideStage && hasChildren && !mMainStage.isActive()) { diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt new file mode 100644 index 000000000000..f64ea4561906 --- /dev/null +++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2023 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.systemui.lint + +import com.android.tools.lint.client.api.UElementHandler +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import com.android.tools.lint.detector.api.SourceCodeScanner +import org.jetbrains.uast.UAnnotation +import org.jetbrains.uast.UElement + +class DemotingTestWithoutBugDetector : Detector(), SourceCodeScanner { + override fun getApplicableUastTypes(): List<Class<out UElement>> { + return listOf(UAnnotation::class.java) + } + + override fun createUastHandler(context: JavaContext): UElementHandler { + return object : UElementHandler() { + override fun visitAnnotation(node: UAnnotation) { + if (node.qualifiedName !in DEMOTING_ANNOTATION) { + return + } + val bugId = node.findAttributeValue("bugId")!!.evaluate() as Int + if (bugId <= 0) { + val location = context.getLocation(node) + val message = "Please attach a bug id to track demoted test" + context.report(ISSUE, node, location, message) + } + } + } + } + + companion object { + val DEMOTING_ANNOTATION = + listOf("androidx.test.filters.FlakyTest", "android.platform.test.annotations.FlakyTest") + + @JvmField + val ISSUE: Issue = + Issue.create( + id = "DemotingTestWithoutBug", + briefDescription = "Demoting a test without attaching a bug.", + explanation = + """ + Annotations (`@FlakyTest`) demote tests to an unmonitored \ + test suite. Please set the `bugId` field in such annotations to track \ + the test status. + """, + category = Category.TESTING, + priority = 8, + severity = Severity.WARNING, + implementation = + Implementation( + DemotingTestWithoutBugDetector::class.java, + Scope.JAVA_FILE_SCOPE + ) + ) + } +} diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt index 84f70502fa45..387b67d231cd 100644 --- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt +++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt @@ -39,7 +39,8 @@ class SystemUIIssueRegistry : IssueRegistry() { RegisterReceiverViaContextDetector.ISSUE, SoftwareBitmapDetector.ISSUE, NonInjectedServiceDetector.ISSUE, - StaticSettingsProviderDetector.ISSUE + StaticSettingsProviderDetector.ISSUE, + DemotingTestWithoutBugDetector.ISSUE ) override val api: Int diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt new file mode 100644 index 000000000000..557c300635eb --- /dev/null +++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2023 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.systemui.lint + +import com.android.tools.lint.checks.infrastructure.TestFile +import com.android.tools.lint.checks.infrastructure.TestFiles +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue +import org.junit.Test + +class DemotingTestWithoutBugDetectorTest : SystemUILintDetectorTest() { + + override fun getDetector(): Detector = DemotingTestWithoutBugDetector() + override fun getIssues(): List<Issue> = listOf(DemotingTestWithoutBugDetector.ISSUE) + + @Test + fun testMarkFlaky_withBugId() { + lint() + .files( + TestFiles.java( + """ + package test.pkg; + import androidx.test.filters.FlakyTest; + + @FlakyTest(bugId = 123) + public class TestClass { + public void testCase() {} + } + """ + ) + .indented(), + *stubs + ) + .issues(DemotingTestWithoutBugDetector.ISSUE) + .run() + .expectClean() + + lint() + .files( + TestFiles.java( + """ + package test.pkg; + import android.platform.test.annotations.FlakyTest; + + @FlakyTest(bugId = 123) + public class TestClass { + public void testCase() {} + } + """ + ) + .indented(), + *stubs + ) + .issues(DemotingTestWithoutBugDetector.ISSUE) + .run() + .expectClean() + } + + @Test + fun testMarkFlaky_withoutBugId() { + lint() + .files( + TestFiles.java( + """ + package test.pkg; + import androidx.test.filters.FlakyTest; + + @FlakyTest + public class TestClass { + public void testCase() {} + } + """ + ) + .indented(), + *stubs + ) + .issues(DemotingTestWithoutBugDetector.ISSUE) + .run() + .expect( + """ + src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test [DemotingTestWithoutBug] + @FlakyTest + ~~~~~~~~~~ + 0 errors, 1 warnings + """ + ) + + lint() + .files( + TestFiles.java( + """ + package test.pkg; + import android.platform.test.annotations.FlakyTest; + + @FlakyTest + public class TestClass { + public void testCase() {} + } + """ + ) + .indented(), + *stubs + ) + .issues(DemotingTestWithoutBugDetector.ISSUE) + .run() + .expect( + """ + src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test [DemotingTestWithoutBug] + @FlakyTest + ~~~~~~~~~~ + 0 errors, 1 warnings + """ + ) + } + + private val filtersFlakyTestStub: TestFile = + java( + """ + package androidx.test.filters; + + public @interface FlakyTest { + int bugId() default -1; + } + """ + ) + private val annotationsFlakyTestStub: TestFile = + java( + """ + package android.platform.test.annotations; + + public @interface FlakyTest { + int bugId() default -1; + } + """ + ) + private val stubs = arrayOf(filtersFlakyTestStub, annotationsFlakyTestStub) +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java index c1fae9e44bd3..33bea027cd20 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java @@ -69,6 +69,7 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView { private Interpolator mLinearOutSlowInInterpolator; private Interpolator mFastOutLinearInInterpolator; + private DisappearAnimationListener mDisappearAnimationListener; public KeyguardPasswordView(Context context) { this(context, null); @@ -186,9 +187,13 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView { return; } Insets shownInsets = controller.getShownStateInsets(); - Insets insets = Insets.add(shownInsets, Insets.of(0, 0, 0, - (int) (-shownInsets.bottom / 4 - * anim.getAnimatedFraction()))); + int dist = (int) (-shownInsets.bottom / 4 + * anim.getAnimatedFraction()); + Insets insets = Insets.add(shownInsets, Insets.of(0, 0, 0, dist)); + if (mDisappearAnimationListener != null) { + mDisappearAnimationListener.setTranslationY(-dist); + } + controller.setInsetsAndAlpha(insets, (float) animation.getAnimatedValue(), anim.getAnimatedFraction()); @@ -209,6 +214,7 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView { controller.finish(false); runOnFinishImeAnimationRunnable(); finishRunnable.run(); + mDisappearAnimationListener = null; Trace.endSection(); }); } @@ -286,4 +292,19 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView { } }); } + + /** + * Listens to the progress of the disappear animation and handles it. + */ + interface DisappearAnimationListener { + void setTranslationY(int transY); + } + + /** + * Set an instance of the disappear animation listener to this class. This will be + * removed when the animation completes. + */ + public void setDisappearAnimationListener(DisappearAnimationListener listener) { + mDisappearAnimationListener = listener; + } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index c6f0eeed108f..66d5d097ab04 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -173,6 +173,17 @@ public class KeyguardSecurityContainer extends ConstraintLayout { private @Mode int mCurrentMode = MODE_UNINITIALIZED; private int mWidth = -1; + /** + * This callback is used to animate KeyguardSecurityContainer and its child views based on + * the interaction with the ime. After + * {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)}, + * {@link #onApplyWindowInsets} is called where we + * set the bottom padding to be the height of the keyboard. We use this padding to determine + * the delta of vertical distance for y-translation animations. + * Note that bottom padding is not set when the disappear animation is started because + * we are deferring the y translation logic to the animator in + * {@link KeyguardPasswordView#startDisappearAnimation(Runnable)} + */ private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback = new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) { @@ -213,7 +224,6 @@ public class KeyguardSecurityContainer extends ConstraintLayout { continue; } interpolatedFraction = animation.getInterpolatedFraction(); - final int paddingBottom = (int) MathUtils.lerp( start, end, interpolatedFraction); @@ -568,13 +578,21 @@ public class KeyguardSecurityContainer extends ConstraintLayout { */ public void startDisappearAnimation(SecurityMode securitySelection) { mDisappearAnimRunning = true; - mViewMode.startDisappearAnimation(securitySelection); + if (securitySelection == SecurityMode.Password + && mSecurityViewFlipper.getSecurityView() instanceof KeyguardPasswordView) { + ((KeyguardPasswordView) mSecurityViewFlipper.getSecurityView()) + .setDisappearAnimationListener(this::setTranslationY); + } else { + mViewMode.startDisappearAnimation(securitySelection); + } } /** * This will run when the bouncer shows in all cases except when the user drags the bouncer up. */ public void startAppearAnimation(SecurityMode securityMode) { + setTranslationY(0f); + setAlpha(1f); updateChildren(0 /* translationY */, 1f /* alpha */); mViewMode.startAppearAnimation(securityMode); } @@ -623,7 +641,13 @@ public class KeyguardSecurityContainer extends ConstraintLayout { int inset = max(bottomInset, imeInset); int paddingBottom = max(inset, getContext().getResources() .getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin)); - setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), paddingBottom); + // If security mode is password, we rely on the animation value of defined in + // KeyguardPasswordView to determine the y translation animation. + // This means that we will prevent the WindowInsetsAnimationCallback from setting any y + // translation values by preventing the setting of the padding here. + if (!mDisappearAnimRunning) { + setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), paddingBottom); + } return insets.inset(0, 0, 0, inset); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java index fb016911f913..cb2d6732b130 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java @@ -29,6 +29,7 @@ import com.android.systemui.sensorprivacy.television.TvUnblockSensorActivity; import com.android.systemui.settings.brightness.BrightnessDialog; import com.android.systemui.statusbar.tv.notifications.TvNotificationPanelActivity; import com.android.systemui.tuner.TunerActivity; +import com.android.systemui.usb.UsbAccessoryUriActivity; import com.android.systemui.usb.UsbConfirmActivity; import com.android.systemui.usb.UsbDebuggingActivity; import com.android.systemui.usb.UsbDebuggingSecondaryUserActivity; @@ -94,6 +95,12 @@ public abstract class DefaultActivityBinder { @ClassKey(UsbConfirmActivity.class) public abstract Activity bindUsbConfirmActivity(UsbConfirmActivity activity); + /** Inject into UsbAccessoryUriActivity. */ + @Binds + @IntoMap + @ClassKey(UsbAccessoryUriActivity.class) + public abstract Activity bindUsbAccessoryUriActivity(UsbAccessoryUriActivity activity); + /** Inject into CreateUserActivity. */ @Binds @IntoMap diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java index 73c2289ad6bd..a7b3bbcbc37b 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java @@ -254,7 +254,10 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { mCurrentScrimController = mScrimManager.getCurrentController(); session.registerCallback(() -> { - mVelocityTracker.recycle(); + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } mScrimManager.removeCallback(mScrimManagerCallback); mCapture = null; mNotificationShadeWindowController.setForcePluginOpen(false, this); diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 5ae86b18a16c..9b36b923cf88 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -352,7 +352,7 @@ object Flags { val MEDIA_TTT_RECEIVER_SUCCESS_RIPPLE = releasedFlag(910, "media_ttt_receiver_success_ripple") // TODO(b/263512203): Tracking Bug - val MEDIA_EXPLICIT_INDICATOR = unreleasedFlag(911, "media_explicit_indicator", teamfood = true) + val MEDIA_EXPLICIT_INDICATOR = unreleasedFlag(911, "media_explicit_indicator") // TODO(b/265813373): Tracking Bug val MEDIA_TAP_TO_TRANSFER_DISMISS_GESTURE = releasedFlag(912, "media_ttt_dismiss_gesture") @@ -385,6 +385,9 @@ object Flags { // TODO(b/265045965): Tracking Bug val SHOW_LOWLIGHT_ON_DIRECT_BOOT = releasedFlag(1003, "show_lowlight_on_direct_boot") + @JvmField + val ENABLE_LOW_LIGHT_CLOCK_UNDOCKED = unreleasedFlag(1004, "enable_low_light_clock_undocked") + // 1100 - windowing @Keep @JvmField @@ -461,7 +464,7 @@ object Flags { @Keep @JvmField val ENABLE_PIP_SIZE_LARGE_SCREEN = - sysPropBooleanFlag(1114, "persist.wm.debug.enable_pip_size_large_screen", default = false) + sysPropBooleanFlag(1114, "persist.wm.debug.enable_pip_size_large_screen", default = true) // TODO(b/265998256): Tracking bug @Keep diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 25ff308b46bb..019ca52107dd 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -631,7 +631,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis final NavigationBarView navBarView = mNavBarControllerLazy.get().getNavigationBarView(mContext.getDisplayId()); final NotificationPanelViewController panelController = - mCentralSurfacesOptionalLazy.get().get().getNotificationPanelViewController(); + mCentralSurfacesOptionalLazy.get() + .map(CentralSurfaces::getNotificationPanelViewController) + .orElse(null); if (SysUiState.DEBUG) { Log.d(TAG_OPS, "Updating sysui state flags: navBarFragment=" + navBarFragment + " navBarView=" + navBarView + " panelController=" + panelController); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java index 753032c2ee01..3268032becf8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java @@ -59,7 +59,7 @@ import com.android.systemui.statusbar.notification.PropertyAnimator; import com.android.systemui.statusbar.notification.stack.AnimationProperties; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; import com.android.systemui.statusbar.phone.fragment.StatusBarIconBlocklistKt; -import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventAnimator; +import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventDefaultAnimator; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -75,6 +75,8 @@ import java.util.concurrent.Executor; import javax.inject.Inject; +import kotlin.Unit; + /** View Controller for {@link com.android.systemui.statusbar.phone.KeyguardStatusBarView}. */ public class KeyguardStatusBarViewController extends ViewController<KeyguardStatusBarView> { private static final String TAG = "KeyguardStatusBarViewController"; @@ -123,7 +125,8 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat public void onDensityOrFontScaleChanged() { mView.loadDimens(); // The animator is dependent on resources for offsets - mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, getResources()); + mSystemEventAnimator = + getSystemEventAnimator(mSystemEventAnimator.isAnimationRunning()); } @Override @@ -248,7 +251,8 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat private int mStatusBarState; private boolean mDozing; private boolean mShowingKeyguardHeadsUp; - private StatusBarSystemEventAnimator mSystemEventAnimator; + private StatusBarSystemEventDefaultAnimator mSystemEventAnimator; + private float mSystemEventAnimatorAlpha = 1; /** * The alpha value to be set on the View. If -1, this value is to be ignored. @@ -324,7 +328,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat mView.setKeyguardUserAvatarEnabled( !mStatusBarUserChipViewModel.getChipEnabled()); - mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, r); + mSystemEventAnimator = getSystemEventAnimator(/* isAnimationRunning */ false); mDisableStateTracker = new DisableStateTracker( /* mask1= */ DISABLE_SYSTEM_INFO, @@ -480,6 +484,10 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat * (1.0f - mKeyguardHeadsUpShowingAmount); } + if (mSystemEventAnimator.isAnimationRunning()) { + newAlpha = Math.min(newAlpha, mSystemEventAnimatorAlpha); + } + boolean hideForBypass = mFirstBypassAttempt && mKeyguardUpdateMonitor.shouldListenForFace() || mDelayShowingKeyguardStatusBar; @@ -488,7 +496,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat && !mDozing && !hideForBypass && !mDisableStateTracker.isDisabled() - ? View.VISIBLE : View.INVISIBLE; + ? View.VISIBLE : View.INVISIBLE; updateViewState(newAlpha, newVisibility); } @@ -614,4 +622,15 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat updateBlockedIcons(); } }; + + private StatusBarSystemEventDefaultAnimator getSystemEventAnimator(boolean isAnimationRunning) { + return new StatusBarSystemEventDefaultAnimator(getResources(), (alpha) -> { + mSystemEventAnimatorAlpha = alpha; + updateViewState(); + return Unit.INSTANCE; + }, (translationX) -> { + mView.setTranslationX(translationX); + return Unit.INSTANCE; + }, isAnimationRunning); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt index c04ea36b3d8d..5903fa3d5bd1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt @@ -26,19 +26,39 @@ import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_IN import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_OUT import com.android.systemui.statusbar.events.SystemStatusAnimationCallback import com.android.systemui.util.animation.AnimationUtil.Companion.frames +import com.android.systemui.util.doOnCancel +import com.android.systemui.util.doOnEnd + +/** + * An implementation of [StatusBarSystemEventDefaultAnimator], applying the onAlphaChanged and + * onTranslationXChanged callbacks directly to the provided animatedView. + */ +class StatusBarSystemEventAnimator @JvmOverloads constructor( + val animatedView: View, + resources: Resources, + isAnimationRunning: Boolean = false +) : StatusBarSystemEventDefaultAnimator( + resources = resources, + onAlphaChanged = animatedView::setAlpha, + onTranslationXChanged = animatedView::setTranslationX, + isAnimationRunning = isAnimationRunning +) /** * Tied directly to [SystemStatusAnimationScheduler]. Any StatusBar-like thing (keyguard, collapsed - * status bar fragment), can just feed this an animatable view to get the default system status - * animation. + * status bar fragment), can use this Animator to get the default system status animation. It simply + * needs to implement the onAlphaChanged and onTranslationXChanged callbacks. * * This animator relies on resources, and should be recreated whenever resources are updated. While * this class could be used directly as the animation callback, it's probably best to forward calls * to it so that it can be recreated at any moment without needing to remove/add callback. */ -class StatusBarSystemEventAnimator( - val animatedView: View, - resources: Resources + +open class StatusBarSystemEventDefaultAnimator @JvmOverloads constructor( + resources: Resources, + private val onAlphaChanged: (Float) -> Unit, + private val onTranslationXChanged: (Float) -> Unit, + var isAnimationRunning: Boolean = false ) : SystemStatusAnimationCallback { private val translationXIn: Int = resources.getDimensionPixelSize( R.dimen.ongoing_appops_chip_animation_in_status_bar_translation_x) @@ -46,18 +66,19 @@ class StatusBarSystemEventAnimator( R.dimen.ongoing_appops_chip_animation_out_status_bar_translation_x) override fun onSystemEventAnimationBegin(): Animator { + isAnimationRunning = true val moveOut = ValueAnimator.ofFloat(0f, 1f).apply { duration = 23.frames interpolator = STATUS_BAR_X_MOVE_OUT addUpdateListener { - animatedView.translationX = -(translationXIn * animatedValue as Float) + onTranslationXChanged(-(translationXIn * animatedValue as Float)) } } val alphaOut = ValueAnimator.ofFloat(1f, 0f).apply { duration = 8.frames interpolator = null addUpdateListener { - animatedView.alpha = animatedValue as Float + onAlphaChanged(animatedValue as Float) } } @@ -67,13 +88,13 @@ class StatusBarSystemEventAnimator( } override fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator { - animatedView.translationX = translationXOut.toFloat() + onTranslationXChanged(translationXOut.toFloat()) val moveIn = ValueAnimator.ofFloat(1f, 0f).apply { duration = 23.frames startDelay = 7.frames interpolator = STATUS_BAR_X_MOVE_IN addUpdateListener { - animatedView.translationX = translationXOut * animatedValue as Float + onTranslationXChanged(translationXOut * animatedValue as Float) } } val alphaIn = ValueAnimator.ofFloat(0f, 1f).apply { @@ -81,13 +102,14 @@ class StatusBarSystemEventAnimator( startDelay = 11.frames interpolator = null addUpdateListener { - animatedView.alpha = animatedValue as Float + onAlphaChanged(animatedValue as Float) } } val animatorSet = AnimatorSet() animatorSet.playTogether(moveIn, alphaIn) - + animatorSet.doOnEnd { isAnimationRunning = false } + animatorSet.doOnCancel { isAnimationRunning = false } return animatorSet } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java index d5d3efd78d13..3a7ac9c8a8bd 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java @@ -31,6 +31,9 @@ import android.view.WindowManager; import com.android.internal.app.AlertActivity; import com.android.internal.app.AlertController; import com.android.systemui.R; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; + +import javax.inject.Inject; /** * If the attached USB accessory has a URL associated with it, and that URL is valid, @@ -46,13 +49,27 @@ public class UsbAccessoryUriActivity extends AlertActivity private UsbAccessory mAccessory; private Uri mUri; + private final DeviceProvisionedController mDeviceProvisionedController; + + @Inject + UsbAccessoryUriActivity(DeviceProvisionedController deviceProvisionedController) { + mDeviceProvisionedController = deviceProvisionedController; + } + @Override public void onCreate(Bundle icicle) { - getWindow().addSystemFlags( + getWindow().addSystemFlags( WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); - super.onCreate(icicle); + super.onCreate(icicle); + + // Don't show this dialog during Setup Wizard + if (!mDeviceProvisionedController.isDeviceProvisioned()) { + Log.e(TAG, "device not provisioned"); + finish(); + return; + } - Intent intent = getIntent(); + Intent intent = getIntent(); mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); String uriString = intent.getStringExtra("uri"); mUri = (uriString == null ? null : Uri.parse(uriString)); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java index 1bbc19931c21..531006da8210 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java @@ -37,6 +37,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -160,6 +161,29 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { } @Test + public void testOnApplyWindowInsets_disappearAnimation_paddingNotSet() { + int paddingBottom = getContext().getResources() + .getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin); + int imeInsetAmount = paddingBottom + 1; + int systemBarInsetAmount = 0; + initMode(MODE_DEFAULT); + + Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount); + Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount); + + WindowInsets insets = new WindowInsets.Builder() + .setInsets(ime(), imeInset) + .setInsetsIgnoringVisibility(systemBars(), systemBarInset) + .build(); + + ensureViewFlipperIsMocked(); + mKeyguardSecurityContainer.startDisappearAnimation( + KeyguardSecurityModel.SecurityMode.Password); + mKeyguardSecurityContainer.onApplyWindowInsets(insets); + assertThat(mKeyguardSecurityContainer.getPaddingBottom()).isNotEqualTo(imeInsetAmount); + } + + @Test public void testDefaultViewMode() { initMode(MODE_ONE_HANDED); initMode(MODE_DEFAULT); @@ -376,6 +400,17 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { assertThat(mKeyguardSecurityContainer.getScaleY()).isEqualTo(1); } + @Test + public void testDisappearAnimationPassword() { + ensureViewFlipperIsMocked(); + KeyguardPasswordView keyguardPasswordView = mock(KeyguardPasswordView.class); + when(mSecurityViewFlipper.getSecurityView()).thenReturn(keyguardPasswordView); + + mKeyguardSecurityContainer + .startDisappearAnimation(KeyguardSecurityModel.SecurityMode.Password); + verify(keyguardPasswordView).setDisappearAnimationListener(any()); + } + private BackEvent createBackEvent(float touchX, float progress) { return new BackEvent(0, 0, progress, BackEvent.EDGE_LEFT); } @@ -446,4 +481,12 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { mUserSwitcherController, () -> { }, mFalsingA11yDelegate); } + + private void ensureViewFlipperIsMocked() { + mSecurityViewFlipper = mock(KeyguardSecurityViewFlipper.class); + KeyguardPasswordView keyguardPasswordView = mock(KeyguardPasswordView.class); + when(mSecurityViewFlipper.getSecurityView()).thenReturn(keyguardPasswordView); + mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper; + } + } diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java index 3a168d4e234b..d6dbd730368e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java @@ -450,6 +450,15 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { swipeToPosition(0f, Direction.DOWN, 0); } + @Test + public void testTouchSessionOnRemovedCalledTwice() { + mTouchHandler.onSessionStart(mTouchSession); + ArgumentCaptor<DreamTouchHandler.TouchSession.Callback> onRemovedCallbackCaptor = + ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.Callback.class); + verify(mTouchSession).registerCallback(onRemovedCallbackCaptor.capture()); + onRemovedCallbackCaptor.getValue().onRemoved(); + onRemovedCallbackCaptor.getValue().onRemoved(); + } private void swipeToPosition(float percent, Direction direction, float velocityY) { Mockito.clearInvocations(mTouchSession); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d78fe8628c60..5dcdbd41c6cc 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3831,8 +3831,20 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.w(TAG, msg); throw new SecurityException(msg); } + final int callingUid = Binder.getCallingUid(); + final int callingPid = Binder.getCallingPid(); + final int callingAppId = UserHandle.getAppId(callingUid); - userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), + ProcessRecord proc; + synchronized (mPidsSelfLocked) { + proc = mPidsSelfLocked.get(callingPid); + } + final boolean hasKillAllPermission = PERMISSION_GRANTED == checkPermission( + android.Manifest.permission.FORCE_STOP_PACKAGES, callingPid, callingUid) + || UserHandle.isCore(callingUid) + || (proc != null && proc.info.isSystemApp()); + + userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_FULL_ONLY, "killBackgroundProcesses", null); final int[] userIds = mUserController.expandUserId(userId); @@ -3847,7 +3859,7 @@ public class ActivityManagerService extends IActivityManager.Stub targetUserId)); } catch (RemoteException e) { } - if (appId == -1) { + if (appId == -1 || (!hasKillAllPermission && appId != callingAppId)) { Slog.w(TAG, "Invalid packageName: " + packageName); return; } @@ -3875,6 +3887,22 @@ public class ActivityManagerService extends IActivityManager.Stub throw new SecurityException(msg); } + final int callingUid = Binder.getCallingUid(); + final int callingPid = Binder.getCallingPid(); + + ProcessRecord proc; + synchronized (mPidsSelfLocked) { + proc = mPidsSelfLocked.get(callingPid); + } + if (callingUid >= FIRST_APPLICATION_UID + && (proc == null || !proc.info.isSystemApp())) { + final String msg = "Permission Denial: killAllBackgroundProcesses() from pid=" + + callingPid + ", uid=" + callingUid + " is not allowed"; + Slog.w(TAG, msg); + // Silently return to avoid existing apps from crashing. + return; + } + final long callingId = Binder.clearCallingIdentity(); try { synchronized (this) { diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 2f95716639f0..207c10c44c9b 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -21,7 +21,6 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE; import android.annotation.NonNull; -import android.app.AlarmManager; import android.app.StatsManager; import android.app.usage.NetworkStatsManager; import android.bluetooth.BluetoothActivityEnergyInfo; @@ -357,16 +356,6 @@ public final class BatteryStatsService extends IBatteryStats.Stub mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger( com.android.internal.R.integer.config_radioScanningTimeout) * 1000L); mStats.setPowerProfileLocked(mPowerProfile); - - final boolean resetOnUnplugHighBatteryLevel = context.getResources().getBoolean( - com.android.internal.R.bool.config_batteryStatsResetOnUnplugHighBatteryLevel); - final boolean resetOnUnplugAfterSignificantCharge = context.getResources().getBoolean( - com.android.internal.R.bool.config_batteryStatsResetOnUnplugAfterSignificantCharge); - mStats.setBatteryStatsConfig( - new BatteryStatsImpl.BatteryStatsConfig.Builder() - .setResetOnUnplugHighBatteryLevel(resetOnUnplugHighBatteryLevel) - .setResetOnUnplugAfterSignificantCharge(resetOnUnplugAfterSignificantCharge) - .build()); mStats.startTrackingSystemServerCpuTime(); if (BATTERY_USAGE_STORE_ENABLED) { @@ -397,18 +386,6 @@ public final class BatteryStatsService extends IBatteryStats.Stub Slog.e(TAG, "Could not register INetworkManagement event observer " + e); } - final AlarmManager am = mContext.getSystemService(AlarmManager.class); - mHandler.post(() -> { - synchronized (mStats) { - mStats.setLongPlugInAlarmInterface(new AlarmInterface(am, () -> { - synchronized (mStats) { - if (mStats.isOnBattery()) return; - mStats.maybeResetWhilePluggedInLocked(); - } - })); - } - }); - synchronized (mPowerStatsLock) { mPowerStatsInternal = LocalServices.getService(PowerStatsInternal.class); if (mPowerStatsInternal != null) { @@ -2282,32 +2259,6 @@ public final class BatteryStatsService extends IBatteryStats.Stub } } - final class AlarmInterface implements BatteryStatsImpl.AlarmInterface, - AlarmManager.OnAlarmListener { - private AlarmManager mAm; - private Runnable mOnAlarm; - - AlarmInterface(AlarmManager am, Runnable onAlarm) { - mAm = am; - mOnAlarm = onAlarm; - } - - @Override - public void schedule(long rtcTimeMs, long windowLengthMs) { - mAm.setWindow(AlarmManager.RTC, rtcTimeMs, windowLengthMs, TAG, this, mHandler); - } - - @Override - public void cancel() { - mAm.cancel(this); - } - - @Override - public void onAlarm() { - mOnAlarm.run(); - } - } - private static native int nativeWaitWakeup(ByteBuffer outBuffer); private void dumpHelp(PrintWriter pw) { @@ -2494,8 +2445,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } else if ("--reset-all".equals(arg)) { awaitCompletion(); synchronized (mStats) { - mStats.resetAllStatsAndHistoryLocked( - BatteryStatsImpl.RESET_REASON_ADB_COMMAND); + mStats.resetAllStatsCmdLocked(); mBatteryUsageStatsStore.removeAllSnapshots(); pw.println("Battery stats and history reset."); noOutput = true; @@ -2503,8 +2453,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } else if ("--reset".equals(arg)) { awaitCompletion(); synchronized (mStats) { - mStats.resetAllStatsAndHistoryLocked( - BatteryStatsImpl.RESET_REASON_ADB_COMMAND); + mStats.resetAllStatsCmdLocked(); pw.println("Battery stats reset."); noOutput = true; } diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 350aa6b2f686..2a807b2a3ef3 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -608,6 +608,9 @@ class MediaRouter2ServiceImpl { /* package */ void updateRunningUserAndProfiles(int newActiveUserId) { synchronized (mLock) { if (mCurrentActiveUserId != newActiveUserId) { + Slog.i(TAG, TextUtils.formatSimple( + "switchUser | user: %d", newActiveUserId)); + mCurrentActiveUserId = newActiveUserId; for (int i = 0; i < mUserRecords.size(); i++) { int userId = mUserRecords.keyAt(i); @@ -679,6 +682,10 @@ class MediaRouter2ServiceImpl { userRecord.mHandler.sendMessage( obtainMessage(UserHandler::notifyRouterRegistered, userRecord.mHandler, routerRecord)); + + Slog.i(TAG, TextUtils.formatSimple( + "registerRouter2 | package: %s, uid: %d, pid: %d, router: %d", + packageName, uid, pid, routerRecord.mRouterId)); } @GuardedBy("mLock") @@ -689,6 +696,11 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "unregisterRouter2 | package: %s, router: %d", + routerRecord.mPackageName, + routerRecord.mRouterId)); + UserRecord userRecord = routerRecord.mUserRecord; userRecord.mRouterRecords.remove(routerRecord); routerRecord.mUserRecord.mHandler.sendMessage( @@ -707,6 +719,11 @@ class MediaRouter2ServiceImpl { if (routerRecord.mDiscoveryPreference.equals(discoveryRequest)) { return; } + + Slog.i(TAG, TextUtils.formatSimple( + "setDiscoveryRequestWithRouter2 | router: %d, discovery request: %s", + routerRecord.mRouterId, discoveryRequest.toString())); + routerRecord.mDiscoveryPreference = discoveryRequest; routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::notifyDiscoveryPreferenceChangedToManagers, @@ -724,6 +741,10 @@ class MediaRouter2ServiceImpl { RouterRecord routerRecord = mAllRouterRecords.get(binder); if (routerRecord != null) { + Slog.i(TAG, TextUtils.formatSimple( + "setRouteVolumeWithRouter2 | router: %d, volume: %d", + routerRecord.mRouterId, volume)); + routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::setRouteVolumeOnHandler, routerRecord.mUserRecord.mHandler, @@ -804,6 +825,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "selectRouteWithRouter2 | router: %d, route: %s", + routerRecord.mRouterId, route.getId())); + routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::selectRouteOnHandler, routerRecord.mUserRecord.mHandler, @@ -819,6 +844,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "deselectRouteWithRouter2 | router: %d, route: %s", + routerRecord.mRouterId, route.getId())); + routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::deselectRouteOnHandler, routerRecord.mUserRecord.mHandler, @@ -834,6 +863,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "transferToRouteWithRouter2 | router: %d, route: %s", + routerRecord.mRouterId, route.getId())); + String defaultRouteId = routerRecord.mUserRecord.mHandler.mSystemProvider.getDefaultRoute().getId(); if (route.isSystemRoute() && !routerRecord.mHasModifyAudioRoutingPermission @@ -859,6 +892,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "setSessionVolumeWithRouter2 | router: %d, session: %s, volume: %d", + routerRecord.mRouterId, uniqueSessionId, volume)); + routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::setSessionVolumeOnHandler, routerRecord.mUserRecord.mHandler, @@ -874,6 +911,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "releaseSessionWithRouter2 | router: %d, session: %s", + routerRecord.mRouterId, uniqueSessionId)); + routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::releaseSessionOnHandler, routerRecord.mUserRecord.mHandler, @@ -916,6 +957,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "registerManager | uid: %d, pid: %d, package: %s, user: %d", + uid, pid, packageName, userId)); + mContext.enforcePermission(Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid, "Must hold MEDIA_CONTENT_CONTROL permission."); @@ -951,6 +996,13 @@ class MediaRouter2ServiceImpl { return; } UserRecord userRecord = managerRecord.mUserRecord; + + Slog.i(TAG, TextUtils.formatSimple( + "unregisterManager | package: %s, user: %d, manager: %d", + managerRecord.mPackageName, + userRecord.mUserId, + managerRecord.mManagerId)); + userRecord.mManagerRecords.remove(managerRecord); managerRecord.dispose(); disposeUserIfNeededLocked(userRecord); // since manager removed from user @@ -962,6 +1014,10 @@ class MediaRouter2ServiceImpl { if (managerRecord == null) { return; } + + Slog.i(TAG, TextUtils.formatSimple( + "startScan | manager: %d", managerRecord.mManagerId)); + managerRecord.startScan(); } @@ -971,6 +1027,10 @@ class MediaRouter2ServiceImpl { if (managerRecord == null) { return; } + + Slog.i(TAG, TextUtils.formatSimple( + "stopScan | manager: %d", managerRecord.mManagerId)); + managerRecord.stopScan(); } @@ -984,6 +1044,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "setRouteVolumeWithManager | manager: %d, route: %s, volume: %d", + managerRecord.mManagerId, route.getId(), volume)); + long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId); managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::setRouteVolumeOnHandler, @@ -999,6 +1063,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "requestCreateSessionWithManager | manager: %d, route: %s", + managerRecord.mManagerId, route.getId())); + String packageName = oldSession.getClientPackageName(); RouterRecord routerRecord = managerRecord.mUserRecord.findRouterRecordLocked(packageName); @@ -1044,6 +1112,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "selectRouteWithManager | manager: %d, session: %s, route: %s", + managerRecord.mManagerId, uniqueSessionId, route.getId())); + // Can be null if the session is system's or RCN. RouterRecord routerRecord = managerRecord.mUserRecord.mHandler .findRouterWithSessionLocked(uniqueSessionId); @@ -1065,6 +1137,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "deselectRouteWithManager | manager: %d, session: %s, route: %s", + managerRecord.mManagerId, uniqueSessionId, route.getId())); + // Can be null if the session is system's or RCN. RouterRecord routerRecord = managerRecord.mUserRecord.mHandler .findRouterWithSessionLocked(uniqueSessionId); @@ -1086,6 +1162,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "transferToRouteWithManager | manager: %d, session: %s, route: %s", + managerRecord.mManagerId, uniqueSessionId, route.getId())); + // Can be null if the session is system's or RCN. RouterRecord routerRecord = managerRecord.mUserRecord.mHandler .findRouterWithSessionLocked(uniqueSessionId); @@ -1107,6 +1187,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "setSessionVolumeWithManager | manager: %d, session: %s, volume: %d", + managerRecord.mManagerId, uniqueSessionId, volume)); + long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId); managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::setSessionVolumeOnHandler, @@ -1124,6 +1208,10 @@ class MediaRouter2ServiceImpl { return; } + Slog.i(TAG, TextUtils.formatSimple( + "releaseSessionWithManager | manager: %d, session: %s", + managerRecord.mManagerId, uniqueSessionId)); + RouterRecord routerRecord = managerRecord.mUserRecord.mHandler .findRouterWithSessionLocked(uniqueSessionId); @@ -1484,6 +1572,24 @@ class MediaRouter2ServiceImpl { List<IMediaRouter2> routersWithModifyAudioRoutingPermission = getRouters(true); List<IMediaRouter2> routersWithoutModifyAudioRoutingPermission = getRouters(false); + + if (!addedRoutes.isEmpty()) { + // If routes were added, currentInfo cannot be null. + Slog.i(TAG, + toLoggingMessage( + /* source= */ "addProviderRoutes", + currentInfo.getUniqueId(), + (ArrayList) addedRoutes)); + } + if (!removedRoutes.isEmpty()) { + // If routes were removed, prevInfo cannot be null. + Slog.i(TAG, + toLoggingMessage( + /* source= */ "removeProviderRoutes", + prevInfo.getUniqueId(), + (ArrayList) removedRoutes)); + } + List<IMediaRouter2Manager> managers = getManagers(); List<MediaRoute2Info> defaultRoute = new ArrayList<>(); defaultRoute.add(mSystemProvider.getDefaultRoute()); @@ -1522,6 +1628,16 @@ class MediaRouter2ServiceImpl { } } + private static String toLoggingMessage( + String source, String providerId, ArrayList<MediaRoute2Info> routes) { + String routesString = + routes.stream() + .map(it -> String.format("%s | %s", it.getOriginalId(), it.getName())) + .collect(Collectors.joining(/* delimiter= */ ", ")); + return TextUtils.formatSimple("%s | provider: %s, routes: [%s]", + source, providerId, routesString); + } + private int getLastProviderInfoIndex(@NonNull String providerId) { for (int i = 0; i < mLastProviderInfos.size(); i++) { MediaRoute2ProviderInfo providerInfo = mLastProviderInfos.get(i); diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java index b75ba75e028b..c5a337d853a6 100644 --- a/services/core/java/com/android/server/media/MediaSessionStack.java +++ b/services/core/java/com/android/server/media/MediaSessionStack.java @@ -21,7 +21,9 @@ import static com.android.server.media.MediaSessionPolicyProvider.SESSION_POLICY import android.media.Session2Token; import android.media.session.MediaSession; import android.os.UserHandle; +import android.text.TextUtils; import android.util.Log; +import android.util.Slog; import android.util.SparseArray; import java.io.PrintWriter; @@ -82,6 +84,10 @@ class MediaSessionStack { * @param record The record to add. */ public void addSession(MediaSessionRecordImpl record) { + Slog.i(TAG, TextUtils.formatSimple( + "addSession to bottom of stack | record: %s", + record + )); mSessions.add(record); clearCache(record.getUserId()); @@ -97,6 +103,10 @@ class MediaSessionStack { * @param record The record to remove. */ public void removeSession(MediaSessionRecordImpl record) { + Slog.i(TAG, TextUtils.formatSimple( + "removeSession | record: %s", + record + )); mSessions.remove(record); if (mMediaButtonSession == record) { // When the media button session is removed, nullify the media button session and do not @@ -142,6 +152,10 @@ class MediaSessionStack { public void onPlaybackStateChanged( MediaSessionRecordImpl record, boolean shouldUpdatePriority) { if (shouldUpdatePriority) { + Slog.i(TAG, TextUtils.formatSimple( + "onPlaybackStateChanged - Pushing session to top | record: %s", + record + )); mSessions.remove(record); mSessions.add(0, record); clearCache(record.getUserId()); diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java index 47bdba34ee24..41eb2c92923f 100644 --- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java @@ -359,12 +359,6 @@ final class DisplayRotationCompatPolicy { CAMERA_OPENED_ROTATION_UPDATE_DELAY_MS); } - private void updateOrientationWithWmLock() { - synchronized (mWmService.mGlobalLock) { - mDisplayContent.updateOrientation(); - } - } - private void delayedUpdateOrientationWithWmLock( @NonNull String cameraId, @NonNull String packageName) { synchronized (this) { @@ -375,25 +369,28 @@ final class DisplayRotationCompatPolicy { } mCameraIdPackageBiMap.put(packageName, cameraId); } - ActivityRecord topActivity = mDisplayContent.topRunningActivity( - /* considerKeyguardState= */ true); - if (topActivity == null || topActivity.getTask() == null) { - return; - } - // Checking whether an activity in fullscreen rather than the task as this camera compat - // treatment doesn't cover activity embedding. - if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { - if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) { - topActivity.recomputeConfiguration(); + synchronized (mWmService.mGlobalLock) { + ActivityRecord topActivity = mDisplayContent.topRunningActivity( + /* considerKeyguardState= */ true); + if (topActivity == null || topActivity.getTask() == null) { + return; + } + // Checking whether an activity in fullscreen rather than the task as this camera + // compat treatment doesn't cover activity embedding. + if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { + if (topActivity.mLetterboxUiController + .isOverrideOrientationOnlyForCameraEnabled()) { + topActivity.recomputeConfiguration(); + } + mDisplayContent.updateOrientation(); + return; + } + // Checking that the whole app is in multi-window mode as we shouldn't show toast + // for the activity embedding case. + if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW + && isTreatmentEnabledForActivity(topActivity, /* mustBeFullscreen */ false)) { + showToast(R.string.display_rotation_camera_compat_toast_in_split_screen); } - updateOrientationWithWmLock(); - return; - } - // Checking that the whole app is in multi-window mode as we shouldn't show toast - // for the activity embedding case. - if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW - && isTreatmentEnabledForActivity(topActivity, /* mustBeFullscreen */ false)) { - showToast(R.string.display_rotation_camera_compat_toast_in_split_screen); } } @@ -441,18 +438,20 @@ final class DisplayRotationCompatPolicy { ProtoLog.v(WM_DEBUG_ORIENTATION, "Display id=%d is notified that Camera %s is closed, updating rotation.", mDisplayContent.mDisplayId, cameraId); - ActivityRecord topActivity = mDisplayContent.topRunningActivity( - /* considerKeyguardState= */ true); - if (topActivity == null - // Checking whether an activity in fullscreen rather than the task as this camera - // compat treatment doesn't cover activity embedding. - || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) { - return; - } - if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) { - topActivity.recomputeConfiguration(); + synchronized (mWmService.mGlobalLock) { + ActivityRecord topActivity = mDisplayContent.topRunningActivity( + /* considerKeyguardState= */ true); + if (topActivity == null + // Checking whether an activity in fullscreen rather than the task as this + // camera compat treatment doesn't cover activity embedding. + || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) { + return; + } + if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) { + topActivity.recomputeConfiguration(); + } + mDisplayContent.updateOrientation(); } - updateOrientationWithWmLock(); } private boolean isActivityForCameraIdRefreshing(String cameraId) { |