blob: 20d57f2d5c34c2ec3034fb582fdc37f952938ecc [file] [log] [blame]
/*
* Copyright (C) 2017 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.wallpaper.module;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import com.android.wallpaper.model.WallpaperMetadata;
import com.android.wallpaper.module.WallpaperPreferences.PresentationMode;
import com.android.wallpaper.module.WallpaperRefresher.RefreshListener;
import com.android.wallpaper.util.DiskBasedLogger;
import java.util.Calendar;
import androidx.annotation.Nullable;
/**
* Performs daily logging operations when alarm is received.
*/
public class DailyLoggingAlarmReceiver extends BroadcastReceiver {
private static final String TAG = "DailyLoggingAlarm";
/**
* Releases the provided WakeLock if and only if it's currently held as to avoid throwing a
* "WakeLock under-locked" RuntimeException.
*/
private static void releaseWakeLock(WakeLock wakeLock) {
if (wakeLock.isHeld()) {
wakeLock.release();
}
}
@Override
public void onReceive(Context context, Intent intent) {
Context appContext = context.getApplicationContext();
Injector injector = InjectorProvider.getInjector();
UserEventLogger logger = injector.getUserEventLogger(appContext);
WallpaperPreferences preferences = injector.getPreferences(appContext);
logger.logNumDailyWallpaperRotationsInLastWeek();
logger.logNumDailyWallpaperRotationsPreviousDay();
logger.logWallpaperPresentationMode();
logger.logSnapshot();
preferences.setLastDailyLogTimestamp(System.currentTimeMillis());
logDailyWallpaperRotationStatus(appContext);
// Clear disk-based logs older than 7 days if they exist.
DiskBasedLogger.clearOldLogs(appContext);
}
/**
* If daily wallpapers are currently in effect and were enabled more than 24 hours ago, then log
* the last-known rotation status as reported by the periodic background rotation components
* (BackdropAlarmReceiver and BackdropRotationTask), or if there wasn't any status update in the
* last 24 hours then log a "not attempted" status to the UserEventLogger.
*/
private void logDailyWallpaperRotationStatus(Context appContext) {
// Acquire a partial wakelock because logging the daily rotation requires doing some work on
// another thread (via AsyncTask) after #onReceive returns, after which the kernel may power
// down and prevent our daily rotation log from being sent.
PowerManager powerManager = (PowerManager) appContext.getSystemService(Context.POWER_SERVICE);
final WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
wakeLock.acquire(10000 /* timeout */);
final Injector injector = InjectorProvider.getInjector();
// First check if rotation is still in effect.
injector.getWallpaperRefresher(appContext).refresh(new RefreshListener() {
@Override
public void onRefreshed(WallpaperMetadata homeWallpaperMetadata,
@Nullable WallpaperMetadata lockWallpaperMetadata,
@PresentationMode int presentationMode) {
// Don't log or do anything else if presentation mode is not rotating.
if (presentationMode != WallpaperPreferences.PRESENTATION_MODE_ROTATING) {
releaseWakeLock(wakeLock);
return;
}
WallpaperPreferences preferences = injector.getPreferences(appContext);
long dailyWallpaperEnabledTimestamp = preferences.getDailyWallpaperEnabledTimestamp();
// Validate the daily wallpaper enabled timestamp.
if (dailyWallpaperEnabledTimestamp < 0) {
Log.e(TAG, "There's no valid daily wallpaper enabled timestamp");
releaseWakeLock(wakeLock);
return;
}
Calendar midnightYesterday = Calendar.getInstance();
midnightYesterday.add(Calendar.DAY_OF_MONTH, -1);
midnightYesterday.set(Calendar.HOUR_OF_DAY, 0);
midnightYesterday.set(Calendar.MINUTE, 0);
// Exclude rotations that were put into affect later than midnight yesterday because the
// background task may not have had a chance to execute yet.
if (dailyWallpaperEnabledTimestamp > midnightYesterday.getTimeInMillis()) {
releaseWakeLock(wakeLock);
return;
}
try {
long lastRotationStatusTimestamp =
preferences.getDailyWallpaperLastRotationStatusTimestamp();
UserEventLogger logger = injector.getUserEventLogger(appContext);
// If a rotation status was reported more recently than midnight yesterday, then log it.
// Otherwise, log a "not attempted" rotation status.
if (lastRotationStatusTimestamp > midnightYesterday.getTimeInMillis()) {
int lastDailyWallpaperRotationStatus =
preferences.getDailyWallpaperLastRotationStatus();
logger.logDailyWallpaperRotationStatus(lastDailyWallpaperRotationStatus);
// If the daily rotation status is "failed", increment the num days failed in
// SharedPreferences and log it, otherwise reset the counter in SharedPreferences to 0.
if (UserEventLogger.ROTATION_STATUS_FAILED == lastDailyWallpaperRotationStatus) {
preferences.incrementNumDaysDailyRotationFailed();
logger.logNumDaysDailyRotationFailed(preferences.getNumDaysDailyRotationFailed());
} else {
preferences.resetNumDaysDailyRotationFailed();
}
// If there was a valid rotation status reported since midnight yesterday, then reset
// the counter for consecutive days of "not attempted".
preferences.resetNumDaysDailyRotationNotAttempted();
} else {
logger.logDailyWallpaperRotationStatus(UserEventLogger.ROTATION_STATUS_NOT_ATTEMPTED);
// Increment and log the consecutive # days in a row that daily rotation was not
// attempted.
preferences.incrementNumDaysDailyRotationNotAttempted();
logger.logNumDaysDailyRotationNotAttempted(
preferences.getNumDaysDailyRotationNotAttempted());
// Reset the disk-based counter for number of consecutive days daily rotation failed
// because if rotation was not attempted but restarts tomorrow after a boot and fails
// then, we want to report that as 1 day of failure instead of 3 consecutive days.
preferences.resetNumDaysDailyRotationFailed();
}
} finally {
releaseWakeLock(wakeLock);
}
}
});
}
}