alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Android example source code file (UsageStatsService.java)

This example Android source code file (UsageStatsService.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Android by Example" TM.

Java - Android tags/keywords

android, app, arraylist, content, failed, file, hashmap, hashset, io, ioexception, launch_time_bins, nc, object, os, parcel, pkgusagestatsextended, string, stringbuilder, timestats, util

The UsageStatsService.java Android example source code

/*
 * Copyright (C) 2006-2007 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.am;

import com.android.internal.app.IUsageStats;

import android.content.ComponentName;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
import com.android.internal.os.PkgUsageStats;
import android.os.Parcel;
import android.os.Process;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.util.Slog;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

/**
 * This service collects the statistics associated with usage
 * of various components, like when a particular package is launched or
 * paused and aggregates events like number of time a component is launched
 * total duration of a component launch.
 */
public final class UsageStatsService extends IUsageStats.Stub {
    public static final String SERVICE_NAME = "usagestats";
    private static final boolean localLOGV = false;
    private static final String TAG = "UsageStats";
    
    // Current on-disk Parcel version
    private static final int VERSION = 1005;

    private static final int CHECKIN_VERSION = 4;
    
    private static final String FILE_PREFIX = "usage-";
    
    private static final int FILE_WRITE_INTERVAL = 30*60*1000; //ms
    
    private static final int MAX_NUM_FILES = 5;
    
    private static final int NUM_LAUNCH_TIME_BINS = 10;
    private static final int[] LAUNCH_TIME_BINS = {
        250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000
    };
    
    static IUsageStats sService;
    private Context mContext;
    // structure used to maintain statistics since the last checkin.
    final private Map<String, PkgUsageStatsExtended> mStats;
    // Lock to update package stats. Methods suffixed by SLOCK should invoked with
    // this lock held
    final Object mStatsLock;
    // Lock to write to file. Methods suffixed by FLOCK should invoked with
    // this lock held.
    final Object mFileLock;
    // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks
    private String mLastResumedPkg;
    private String mLastResumedComp;
    private boolean mIsResumed;
    private File mFile;
    private String mFileLeaf;
    //private File mBackupFile;
    private long mLastWriteElapsedTime;
    private File mDir;
    private Calendar mCal;
    private int mLastWriteDay;
    
    static class TimeStats {
        int count;
        int[] times = new int[NUM_LAUNCH_TIME_BINS];
        
        TimeStats() {
        }
        
        void incCount() {
            count++;
        }
        
        void add(int val) {
            final int[] bins = LAUNCH_TIME_BINS;
            for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
                if (val < bins[i]) {
                    times[i]++;
                    return;
                }
            }
            times[NUM_LAUNCH_TIME_BINS-1]++;
        }
        
        TimeStats(Parcel in) {
            count = in.readInt();
            final int[] localTimes = times;
            for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
                localTimes[i] = in.readInt();
            }
        }
        
        void writeToParcel(Parcel out) {
            out.writeInt(count);
            final int[] localTimes = times;
            for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
                out.writeInt(localTimes[i]);
            }
        }
    }
    
    private class PkgUsageStatsExtended {
        final HashMap<String, TimeStats> mLaunchTimes
                = new HashMap<String, TimeStats>();
        int mLaunchCount;
        long mUsageTime;
        long mPausedTime;
        long mResumedTime;
        
        PkgUsageStatsExtended() {
            mLaunchCount = 0;
            mUsageTime = 0;
        }
        
        PkgUsageStatsExtended(Parcel in) {
            mLaunchCount = in.readInt();
            mUsageTime = in.readLong();
            if (localLOGV) Slog.v(TAG, "Launch count: " + mLaunchCount
                    + ", Usage time:" + mUsageTime);
            
            final int N = in.readInt();
            if (localLOGV) Slog.v(TAG, "Reading comps: " + N);
            for (int i=0; i<N; i++) {
                String comp = in.readString();
                if (localLOGV) Slog.v(TAG, "Component: " + comp);
                TimeStats times = new TimeStats(in);
                mLaunchTimes.put(comp, times);
            }
        }
        
        void updateResume(boolean launched) {
            if (launched) {
                mLaunchCount ++;
            }
            mResumedTime = SystemClock.elapsedRealtime();
        }
        
        void updatePause() {
            mPausedTime =  SystemClock.elapsedRealtime();
            mUsageTime += (mPausedTime - mResumedTime);
        }
        
        void addLaunchCount(String comp) {
            TimeStats times = mLaunchTimes.get(comp);
            if (times == null) {
                times = new TimeStats();
                mLaunchTimes.put(comp, times);
            }
            times.incCount();
        }
        
        void addLaunchTime(String comp, int millis) {
            TimeStats times = mLaunchTimes.get(comp);
            if (times == null) {
                times = new TimeStats();
                mLaunchTimes.put(comp, times);
            }
            times.add(millis);
        }
        
        void writeToParcel(Parcel out) {
            out.writeInt(mLaunchCount);
            out.writeLong(mUsageTime);
            final int N = mLaunchTimes.size();
            out.writeInt(N);
            if (N > 0) {
                for (Map.Entry<String, TimeStats> ent : mLaunchTimes.entrySet()) {
                    out.writeString(ent.getKey());
                    TimeStats times = ent.getValue();
                    times.writeToParcel(out);
                }
            }
        }
        
        void clear() {
            mLaunchTimes.clear();
            mLaunchCount = 0;
            mUsageTime = 0;
        }
    }
    
    UsageStatsService(String dir) {
        mStats = new HashMap<String, PkgUsageStatsExtended>();
        mStatsLock = new Object();
        mFileLock = new Object();
        mDir = new File(dir);
        mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
        
        mDir.mkdir();
        
        // Remove any old usage files from previous versions.
        File parentDir = mDir.getParentFile();
        String fList[] = parentDir.list();
        if (fList != null) {
            String prefix = mDir.getName() + ".";
            int i = fList.length;
            while (i > 0) {
                i--;
                if (fList[i].startsWith(prefix)) {
                    Slog.i(TAG, "Deleting old usage file: " + fList[i]);
                    (new File(parentDir, fList[i])).delete();
                }
            }
        }
        
        // Update current stats which are binned by date
        mFileLeaf = getCurrentDateStr(FILE_PREFIX);
        mFile = new File(mDir, mFileLeaf);
        readStatsFromFile();
        mLastWriteElapsedTime = SystemClock.elapsedRealtime();
        // mCal was set by getCurrentDateStr(), want to use that same time.
        mLastWriteDay = mCal.get(Calendar.DAY_OF_YEAR);
    }

    /*
     * Utility method to convert date into string.
     */
    private String getCurrentDateStr(String prefix) {
        mCal.setTimeInMillis(System.currentTimeMillis());
        StringBuilder sb = new StringBuilder();
        if (prefix != null) {
            sb.append(prefix);
        }
        sb.append(mCal.get(Calendar.YEAR));
        int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1;
        if (mm < 10) {
            sb.append("0");
        }
        sb.append(mm);
        int dd = mCal.get(Calendar.DAY_OF_MONTH);
        if (dd < 10) {
            sb.append("0");
        }
        sb.append(dd);
        return sb.toString();
    }
    
    private Parcel getParcelForFile(File file) throws IOException {
        FileInputStream stream = new FileInputStream(file);
        byte[] raw = readFully(stream);
        Parcel in = Parcel.obtain();
        in.unmarshall(raw, 0, raw.length);
        in.setDataPosition(0);
        stream.close();
        return in;
    }
    
    private void readStatsFromFile() {
        File newFile = mFile;
        synchronized (mFileLock) {
            try {
                if (newFile.exists()) {
                    readStatsFLOCK(newFile);
                } else {
                    // Check for file limit before creating a new file
                    checkFileLimitFLOCK();
                    newFile.createNewFile();
                }
            } catch (IOException e) {
                Slog.w(TAG,"Error : " + e + " reading data from file:" + newFile);
            }
        }
    }
    
    private void readStatsFLOCK(File file) throws IOException {
        Parcel in = getParcelForFile(file);
        int vers = in.readInt();
        if (vers != VERSION) {
            Slog.w(TAG, "Usage stats version changed; dropping");
            return;
        }
        int N = in.readInt();
        while (N > 0) {
            N--;
            String pkgName = in.readString();
            if (pkgName == null) {
                break;
            }
            if (localLOGV) Slog.v(TAG, "Reading package #" + N + ": " + pkgName);
            PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
            synchronized (mStatsLock) {
                mStats.put(pkgName, pus);
            }
        }
    }

    private ArrayList<String> getUsageStatsFileListFLOCK() {
        // Check if there are too many files in the system and delete older files
        String fList[] = mDir.list();
        if (fList == null) {
            return null;
        }
        ArrayList<String> fileList = new ArrayList();
        for (String file : fList) {
            if (!file.startsWith(FILE_PREFIX)) {
                continue;
            }
            if (file.endsWith(".bak")) {
                (new File(mDir, file)).delete();
                continue;
            }
            fileList.add(file);
        }
        return fileList;
    }
    
    private void checkFileLimitFLOCK() {
        // Get all usage stats output files
        ArrayList<String> fileList = getUsageStatsFileListFLOCK();
        if (fileList == null) {
            // Strange but we dont have to delete any thing
            return;
        }
        int count = fileList.size();
        if (count <= MAX_NUM_FILES) {
            return;
        }
        // Sort files
        Collections.sort(fileList);
        count -= MAX_NUM_FILES;
        // Delete older files
        for (int i = 0; i < count; i++) {
            String fileName = fileList.get(i);
            File file = new File(mDir, fileName);
            Slog.i(TAG, "Deleting usage file : " + fileName);
            file.delete();
        }
    }
    
    private void writeStatsToFile(boolean force) {
        synchronized (mFileLock) {
            mCal.setTimeInMillis(System.currentTimeMillis());
            final int curDay = mCal.get(Calendar.DAY_OF_YEAR);
            // Determine if the day changed...  note that this will be wrong
            // if the year has changed but we are in the same day of year...
            // we can probably live with this.
            final boolean dayChanged =  curDay != mLastWriteDay;
            long currElapsedTime = SystemClock.elapsedRealtime();
            if (!force) {
                if (((currElapsedTime-mLastWriteElapsedTime) < FILE_WRITE_INTERVAL) &&
                        (!dayChanged)) {
                    // wait till the next update
                    return;
                }
            }
            // Get the most recent file
            mFileLeaf = getCurrentDateStr(FILE_PREFIX);
            // Copy current file to back up
            File backupFile = null;
            if (mFile != null && mFile.exists()) {
                backupFile = new File(mFile.getPath() + ".bak");
                if (!backupFile.exists()) {
                    if (!mFile.renameTo(backupFile)) {
                        Slog.w(TAG, "Failed to persist new stats");
                        return;
                    }
                } else {
                    mFile.delete();
                }
            }

            try {
                // Write mStats to file
                writeStatsFLOCK();
                mLastWriteElapsedTime = currElapsedTime;
                if (dayChanged) {
                    mLastWriteDay = curDay;
                    // clear stats
                    synchronized (mStats) {
                        mStats.clear();
                    }
                    mFile = new File(mDir, mFileLeaf);
                    checkFileLimitFLOCK();
                }
                // Delete the backup file
                if (backupFile != null) {
                    backupFile.delete();
                }
            } catch (IOException e) {
                Slog.w(TAG, "Failed writing stats to file:" + mFile);
                if (backupFile != null) {
                    mFile.delete();
                    backupFile.renameTo(mFile);
                }
            }
        }
    }

    private void writeStatsFLOCK() throws IOException {
        FileOutputStream stream = new FileOutputStream(mFile);
        try {
            Parcel out = Parcel.obtain();
            writeStatsToParcelFLOCK(out);
            stream.write(out.marshall());
            out.recycle();
            stream.flush();
        } finally {
            stream.close();
        }
    }

    private void writeStatsToParcelFLOCK(Parcel out) {
        synchronized (mStatsLock) {
            out.writeInt(VERSION);
            Set<String> keys = mStats.keySet();
            out.writeInt(keys.size());
            for (String key : keys) {
                PkgUsageStatsExtended pus = mStats.get(key);
                out.writeString(key);
                pus.writeToParcel(out);
            }
        }
    }

    public void publish(Context context) {
        mContext = context;
        ServiceManager.addService(SERVICE_NAME, asBinder());
    }
    
    public void shutdown() {
        Slog.w(TAG, "Writing usage stats before shutdown...");
        writeStatsToFile(true);
    }
    
    public static IUsageStats getService() {
        if (sService != null) {
            return sService;
        }
        IBinder b = ServiceManager.getService(SERVICE_NAME);
        sService = asInterface(b);
        return sService;
    }
    
    public void noteResumeComponent(ComponentName componentName) {
        enforceCallingPermission();
        String pkgName;
        synchronized (mStatsLock) {
            if ((componentName == null) ||
                    ((pkgName = componentName.getPackageName()) == null)) {
                return;
            }
            
            final boolean samePackage = pkgName.equals(mLastResumedPkg);
            if (mIsResumed) {
                if (mLastResumedPkg != null) {
                    // We last resumed some other package...  just pause it now
                    // to recover.
                    Slog.i(TAG, "Unexpected resume of " + pkgName
                            + " while already resumed in " + mLastResumedPkg);
                    PkgUsageStatsExtended pus = mStats.get(mLastResumedPkg);
                    if (pus != null) {
                        pus.updatePause();
                    }
                }
            }
            
            final boolean sameComp = samePackage
                    && componentName.getClassName().equals(mLastResumedComp);
            
            mIsResumed = true;
            mLastResumedPkg = pkgName;
            mLastResumedComp = componentName.getClassName();
            
            if (localLOGV) Slog.i(TAG, "started component:" + pkgName);
            PkgUsageStatsExtended pus = mStats.get(pkgName);
            if (pus == null) {
                pus = new PkgUsageStatsExtended();
                mStats.put(pkgName, pus);
            }
            pus.updateResume(!samePackage);
            if (!sameComp) {
                pus.addLaunchCount(mLastResumedComp);
            }
        }
    }

    public void notePauseComponent(ComponentName componentName) {
        enforceCallingPermission();
        
        synchronized (mStatsLock) {
            String pkgName;
            if ((componentName == null) ||
                    ((pkgName = componentName.getPackageName()) == null)) {
                return;
            }
            if (!mIsResumed) {
                Slog.i(TAG, "Something wrong here, didn't expect "
                        + pkgName + " to be paused");
                return;
            }
            mIsResumed = false;
            
            if (localLOGV) Slog.i(TAG, "paused component:"+pkgName);
        
            PkgUsageStatsExtended pus = mStats.get(pkgName);
            if (pus == null) {
                // Weird some error here
                Slog.i(TAG, "No package stats for pkg:"+pkgName);
                return;
            }
            pus.updatePause();
        }
        
        // Persist current data to file if needed.
        writeStatsToFile(false);
    }
    
    public void noteLaunchTime(ComponentName componentName, int millis) {
        enforceCallingPermission();
        String pkgName;
        if ((componentName == null) ||
                ((pkgName = componentName.getPackageName()) == null)) {
            return;
        }
        
        // Persist current data to file if needed.
        writeStatsToFile(false);
        
        synchronized (mStatsLock) {
            PkgUsageStatsExtended pus = mStats.get(pkgName);
            if (pus != null) {
                pus.addLaunchTime(componentName.getClassName(), millis);
            }
        }
    }
    
    public void enforceCallingPermission() {
        if (Binder.getCallingPid() == Process.myPid()) {
            return;
        }
        mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
                Binder.getCallingPid(), Binder.getCallingUid(), null);
    }
    
    public PkgUsageStats getPkgUsageStats(ComponentName componentName) {
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.PACKAGE_USAGE_STATS, null);
        String pkgName;
        if ((componentName == null) ||
                ((pkgName = componentName.getPackageName()) == null)) {
            return null;
        }
        synchronized (mStatsLock) {
            PkgUsageStatsExtended pus = mStats.get(pkgName);
            if (pus == null) {
               return null;
            }
            return new PkgUsageStats(pkgName, pus.mLaunchCount, pus.mUsageTime);
        }
    }
    
    public PkgUsageStats[] getAllPkgUsageStats() {
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.PACKAGE_USAGE_STATS, null);
        synchronized (mStatsLock) {
            Set<String> keys = mStats.keySet();
            int size = keys.size();
            if (size <= 0) {
                return null;
            }
            PkgUsageStats retArr[] = new PkgUsageStats[size];
            int i = 0;
            for (String key: keys) {
                PkgUsageStatsExtended pus = mStats.get(key);
                retArr[i] = new PkgUsageStats(key, pus.mLaunchCount, pus.mUsageTime);
                i++;
            }
            return retArr;
        }
    }
    
    static byte[] readFully(FileInputStream stream) throws java.io.IOException {
        int pos = 0;
        int avail = stream.available();
        byte[] data = new byte[avail];
        while (true) {
            int amt = stream.read(data, pos, data.length-pos);
            if (amt <= 0) {
                return data;
            }
            pos += amt;
            avail = stream.available();
            if (avail > data.length-pos) {
                byte[] newData = new byte[pos+avail];
                System.arraycopy(data, 0, newData, 0, pos);
                data = newData;
            }
        }
    }
    
    private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput,
            boolean deleteAfterPrint, HashSet<String> packages) {
        List<String> fileList = getUsageStatsFileListFLOCK();
        if (fileList == null) {
            return;
        }
        Collections.sort(fileList);
        for (String file : fileList) {
            if (deleteAfterPrint && file.equalsIgnoreCase(mFileLeaf)) {
                // In this mode we don't print the current day's stats, since
                // they are incomplete.
                continue;
            }
            File dFile = new File(mDir, file);
            String dateStr = file.substring(FILE_PREFIX.length());
            try {
                Parcel in = getParcelForFile(dFile);
                collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput,
                        packages);
                if (deleteAfterPrint) {
                    // Delete old file after collecting info only for checkin requests
                    dFile.delete();
                }
            } catch (FileNotFoundException e) {
                Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : " + file);
                return;
            } catch (IOException e) {
                Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : "+file);
            }      
        }
    }
    
    private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw,
            String date, boolean isCompactOutput, HashSet<String> packages) {
        StringBuilder sb = new StringBuilder(512);
        if (isCompactOutput) {
            sb.append("D:");
            sb.append(CHECKIN_VERSION);
            sb.append(',');
        } else {
            sb.append("Date: ");
        }
        
        sb.append(date);
        
        int vers = in.readInt();
        if (vers != VERSION) {
            sb.append(" (old data version)");
            pw.println(sb.toString());
            return;
        }
        
        pw.println(sb.toString());
        int N = in.readInt();
        
        while (N > 0) {
            N--;
            String pkgName = in.readString();
            if (pkgName == null) {
                break;
            }
            sb.setLength(0);
            PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
            if (packages != null && !packages.contains(pkgName)) {
                // This package has not been requested -- don't print
                // anything for it.
            } else if (isCompactOutput) {
                sb.append("P:");
                sb.append(pkgName);
                sb.append(',');
                sb.append(pus.mLaunchCount);
                sb.append(',');
                sb.append(pus.mUsageTime);
                sb.append('\n');
                final int NC = pus.mLaunchTimes.size();
                if (NC > 0) {
                    for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) {
                        sb.append("A:");
                        String activity = ent.getKey();
                        if (activity.startsWith(pkgName)) {
                            sb.append('*');
                            sb.append(activity.substring(
                                    pkgName.length(), activity.length()));
                        } else {
                            sb.append(activity);
                        }
                        TimeStats times = ent.getValue();
                        sb.append(',');
                        sb.append(times.count);
                        for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
                            sb.append(",");
                            sb.append(times.times[i]);
                        }
                        sb.append('\n');
                    }
                }
                
            } else {
                sb.append("  ");
                sb.append(pkgName);
                sb.append(": ");
                sb.append(pus.mLaunchCount);
                sb.append(" times, ");
                sb.append(pus.mUsageTime);
                sb.append(" ms");
                sb.append('\n');
                final int NC = pus.mLaunchTimes.size();
                if (NC > 0) {
                    for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) {
                        sb.append("    ");
                        sb.append(ent.getKey());
                        TimeStats times = ent.getValue();
                        sb.append(": ");
                        sb.append(times.count);
                        sb.append(" starts");
                        int lastBin = 0;
                        for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
                            if (times.times[i] != 0) {
                                sb.append(", ");
                                sb.append(lastBin);
                                sb.append('-');
                                sb.append(LAUNCH_TIME_BINS[i]);
                                sb.append("ms=");
                                sb.append(times.times[i]);
                            }
                            lastBin = LAUNCH_TIME_BINS[i];
                        }
                        if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) {
                            sb.append(", ");
                            sb.append(">=");
                            sb.append(lastBin);
                            sb.append("ms=");
                            sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]);
                        }
                        sb.append('\n');
                    }
                }
            }
            
            pw.write(sb.toString());
        }
    }
    
    /**
     * Searches array of arguments for the specified string
     * @param args array of argument strings
     * @param value value to search for
     * @return true if the value is contained in the array
     */
    private static boolean scanArgs(String[] args, String value) {
        if (args != null) {
            for (String arg : args) {
                if (value.equals(arg)) {
                    return true;
                }
            }
        }
        return false;
    }
    
    /**
     * Searches array of arguments for the specified string's data
     * @param args array of argument strings
     * @param value value to search for
     * @return the string of data after the arg, or null if there is none
     */
    private static String scanArgsData(String[] args, String value) {
        if (args != null) {
            final int N = args.length;
            for (int i=0; i<N; i++) {
                if (value.equals(args[i])) {
                    i++;
                    return i < N ? args[i] : null;
                }
            }
        }
        return null;
    }
    
    @Override
    /*
     * The data persisted to file is parsed and the stats are computed. 
     */
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        final boolean isCheckinRequest = scanArgs(args, "--checkin");
        final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c");
        final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d");
        final String rawPackages = scanArgsData(args, "--packages");
        
        // Make sure the current stats are written to the file.  This
        // doesn't need to be done if we are deleting files after printing,
        // since it that case we won't print the current stats.
        if (!deleteAfterPrint) {
            writeStatsToFile(true);
        }
        
        HashSet<String> packages = null;
        if (rawPackages != null) {
            if (!"*".equals(rawPackages)) {
                // A * is a wildcard to show all packages.
                String[] names = rawPackages.split(",");
                for (String n : names) {
                    if (packages == null) {
                        packages = new HashSet<String>();
                    }
                    packages.add(n);
                }
            }
        } else if (isCheckinRequest) {
            // If checkin doesn't specify any packages, then we simply won't
            // show anything.
            Slog.w(TAG, "Checkin without packages");
            return;
        }
        
        synchronized (mFileLock) {
            collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint, packages);
        }
    }

}

Other Android examples (source code examples)

Here is a short list of links related to this Android UsageStatsService.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.