Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfe7b70e authored by Kenny Guy's avatar Kenny Guy
Browse files

Daily idle job for writing out brightness events.

Schedule a job for idle + charging to kick off
writing out brighness slider events.
While writing events discard ones outside our
time window.

Bug: 69405990
Test: Manual using adb to kick off job.
Test: runtest -c com.android.server.display.BrightnessTrackerTest frameworks-services
Change-Id: Ibc79d1c80ced26827d6f985bc70ae165df106a42
parent a2dfa95e
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -173,6 +173,11 @@ public abstract class DisplayManagerInternal {
     * */
    public abstract boolean isUidPresentOnDisplay(int uid, int displayId);

    /**
     * Persist brightness slider events.
     */
    public abstract void persistBrightnessSliderEvents();

    /**
     * Describes the requested power state of the display.
     *
+5 −1
Original line number Diff line number Diff line
@@ -3955,6 +3955,10 @@
        <service android:name="com.android.server.net.watchlist.ReportWatchlistJobService"
                 android:permission="android.permission.BIND_JOB_SERVICE" >
        </service>

        <service android:name="com.android.server.display.BrightnessIdleJob"
                 android:permission="android.permission.BIND_JOB_SERVICE" >
        </service>
</application>

</manifest>
+81 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.server.display;


import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.ComponentName;
import android.content.Context;
import android.hardware.display.DisplayManagerInternal;
import android.util.Slog;

import com.android.server.LocalServices;

import java.util.concurrent.TimeUnit;

/**
 * JobService used to persists brightness slider events when the device
 * is idle and charging.
 */
public class BrightnessIdleJob extends JobService {

    // Must be unique within the system server uid.
    private static final int JOB_ID = 3923512;

    public static void scheduleJob(Context context) {
        JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);

        JobInfo pending = jobScheduler.getPendingJob(JOB_ID);
        JobInfo jobInfo =
                new JobInfo.Builder(JOB_ID, new ComponentName(context, BrightnessIdleJob.class))
                        .setRequiresDeviceIdle(true)
                        .setRequiresCharging(true)
                        .setPeriodic(TimeUnit.HOURS.toMillis(24)).build();

        if (pending != null && !pending.equals(jobInfo)) {
            jobScheduler.cancel(JOB_ID);
            pending = null;
        }

        if (pending == null) {
            jobScheduler.schedule(jobInfo);
        }
    }

    public static void cancelJob(Context context) {
        JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
        jobScheduler.cancel(JOB_ID);
    }

    @Override
    public boolean onStartJob(JobParameters params) {
        if (BrightnessTracker.DEBUG) {
            Slog.d(BrightnessTracker.TAG, "Scheduled write of brightness events");
        }
        DisplayManagerInternal dmi = LocalServices.getService(DisplayManagerInternal.class);
        dmi.persistBrightnessSliderEvents();
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return false;
    }
}
 No newline at end of file
+45 −5
Original line number Diff line number Diff line
@@ -61,12 +61,12 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.ArrayList;

import java.util.Deque;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
@@ -75,8 +75,8 @@ import java.util.concurrent.TimeUnit;
 */
public class BrightnessTracker {

    private static final String TAG = "BrightnessTracker";
    private static final boolean DEBUG = false;
    static final String TAG = "BrightnessTracker";
    static final boolean DEBUG = false;

    private static final String EVENTS_FILE = "brightness_events.xml";
    private static final int MAX_EVENTS = 100;
@@ -103,6 +103,8 @@ public class BrightnessTracker {
    @GuardedBy("mEventsLock")
    private RingBuffer<BrightnessChangeEvent> mEvents
            = new RingBuffer<>(BrightnessChangeEvent.class, MAX_EVENTS);
    @GuardedBy("mEventsLock")
    private boolean mEventsDirty;
    private final Runnable mEventsWriter = () -> writeEvents();
    private volatile boolean mWriteEventsScheduled;

@@ -170,6 +172,8 @@ public class BrightnessTracker {
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        mBroadcastReceiver = new Receiver();
        mInjector.registerReceiver(mContext, mBroadcastReceiver, intentFilter);

        mInjector.scheduleIdleJob(mContext);
    }

    /** Stop listening for events */
@@ -181,6 +185,7 @@ public class BrightnessTracker {
        mInjector.unregisterSensorListener(mContext, mSensorListener);
        mInjector.unregisterReceiver(mContext, mBroadcastReceiver);
        mInjector.unregisterBrightnessObserver(mContext, mSettingsObserver);
        mInjector.cancelIdleJob(mContext);
    }

    /**
@@ -211,6 +216,10 @@ public class BrightnessTracker {
                brightness, userId);
    }

    public void persistEvents() {
        scheduleWriteEvents();
    }

    private void handleBrightnessChanged() {
        if (DEBUG) {
            Slog.d(TAG, "Brightness change");
@@ -278,6 +287,7 @@ public class BrightnessTracker {
            Slog.d(TAG, "Event " + event.brightness + " " + event.packageName);
        }
        synchronized (mEventsLock) {
            mEventsDirty = true;
            mEvents.append(event);
        }
    }
@@ -291,8 +301,12 @@ public class BrightnessTracker {

    private void writeEvents() {
        mWriteEventsScheduled = false;
        // TODO kick off write on handler thread e.g. every 24 hours.
        synchronized (mEventsLock) {
            if (!mEventsDirty) {
                // Nothing to write
                return;
            }

            final AtomicFile writeTo = mInjector.getFile();
            if (writeTo == null) {
                return;
@@ -301,12 +315,14 @@ public class BrightnessTracker {
                if (writeTo.exists()) {
                    writeTo.delete();
                }
                mEventsDirty = false;
            } else {
                FileOutputStream output = null;
                try {
                    output = writeTo.startWrite();
                    writeEventsLocked(output);
                    writeTo.finishWrite(output);
                    mEventsDirty = false;
                } catch (IOException e) {
                    writeTo.failWrite(output);
                    Slog.e(TAG, "Failed to write change mEvents.", e);
@@ -317,6 +333,8 @@ public class BrightnessTracker {

    private void readEvents() {
        synchronized (mEventsLock) {
            // Read might prune events so mark as dirty.
            mEventsDirty = true;
            mEvents.clear();
            final AtomicFile readFrom = mInjector.getFile();
            if (readFrom != null && readFrom.exists()) {
@@ -344,13 +362,16 @@ public class BrightnessTracker {

        out.startTag(null, TAG_EVENTS);
        BrightnessChangeEvent[] toWrite = mEvents.toArray();
        // Clear events, code below will add back the ones that are still within the time window.
        mEvents.clear();
        if (DEBUG) {
            Slog.d(TAG, "Writing events " + toWrite.length);
        }
        final long timeCutOff = System.currentTimeMillis() - MAX_EVENT_AGE;
        final long timeCutOff = mInjector.currentTimeMillis() - MAX_EVENT_AGE;
        for (int i = 0; i < toWrite.length; ++i) {
            int userSerialNo = mInjector.getUserSerialNumber(mUserManager, toWrite[i].userId);
            if (userSerialNo != -1 && toWrite[i].timeStamp > timeCutOff) {
                mEvents.append(toWrite[i]);
                out.startTag(null, TAG_EVENT);
                out.attribute(null, ATTR_BRIGHTNESS, Integer.toString(toWrite[i].brightness));
                out.attribute(null, ATTR_TIMESTAMP, Long.toString(toWrite[i].timeStamp));
@@ -465,6 +486,17 @@ public class BrightnessTracker {
        }
    }

    public void dump(PrintWriter pw) {
        synchronized (mEventsLock) {
            pw.println("BrightnessTracker state:");
            pw.println("  mEvents.size=" + mEvents.size());
            pw.println("  mEventsDirty=" + mEventsDirty);
        }
        synchronized (mDataCollectionLock) {
            pw.println("  mLastSensorReadings.size=" + mLastSensorReadings.size());
        }
    }

    // Not allowed to keep the SensorEvent so used to copy the data we care about.
    private static class LightData {
        public float lux;
@@ -635,5 +667,13 @@ public class BrightnessTracker {
        public ActivityManager.StackInfo getFocusedStack() throws RemoteException {
            return ActivityManager.getService().getFocusedStackInfo();
        }

        public void scheduleIdleJob(Context context) {
            BrightnessIdleJob.scheduleJob(context);
        }

        public void cancelIdleJob(Context context) {
            BrightnessIdleJob.cancelJob(context);
        }
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -1285,6 +1285,9 @@ public final class DisplayManagerService extends SystemService {

            pw.println();
            mPersistentDataStore.dump(pw);

            pw.println();
            mBrightnessTracker.dump(pw);
        }
    }

@@ -1921,5 +1924,10 @@ public final class DisplayManagerService extends SystemService {
        public boolean isUidPresentOnDisplay(int uid, int displayId) {
            return isUidPresentOnDisplayInternal(uid, displayId);
        }

        @Override
        public void persistBrightnessSliderEvents() {
            mBrightnessTracker.persistEvents();
        }
    }
}
Loading