Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2019 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #pragma once
     18 
     19 #include <android/content/ComponentName.h>
     20 #include <android/os/IncidentReportArgs.h>
     21 #include <frameworks/base/core/proto/android/os/metadata.pb.h>
     22 #include <frameworks/base/cmds/incidentd/src/report_file.pb.h>
     23 
     24 #include <utils/RefBase.h>
     25 
     26 #include <mutex>
     27 #include <string>
     28 
     29 namespace android {
     30 namespace os {
     31 namespace incidentd {
     32 
     33 using android::content::ComponentName;
     34 using android::os::IncidentReportArgs;
     35 using namespace std;
     36 
     37 extern const ComponentName DROPBOX_SENTINEL;
     38 
     39 class WorkDirectory;
     40 struct WorkDirectoryEntry;
     41 
     42 void get_args_from_report(IncidentReportArgs* out, const ReportFileProto_Report& report);
     43 
     44 /**
     45  * A ReportFile object is backed by two files.
     46  *   - A metadata file, which contains a
     47  */
     48 class ReportFile : public virtual RefBase {
     49 public:
     50     ReportFile(const sp<WorkDirectory>& workDirectory, int64_t timestampNs,
     51             const string& envelopeFileName, const string& dataFileName);
     52 
     53     virtual ~ReportFile();
     54 
     55     /**
     56      * Get the timestamp from when this file was added.
     57      */
     58     int64_t getTimestampNs() const;
     59 
     60     /**
     61      * Add an additional report to this ReportFile.
     62      */
     63     void addReport(const IncidentReportArgs& args);
     64 
     65     /**
     66      * Remove the reports for pkg/cls from this file.
     67      */
     68     void removeReport(const string& pkg, const string& cls);
     69 
     70     /**
     71      * Remove all reports for pkg from this file.
     72      */
     73     void removeReports(const string& pkg);
     74 
     75     /**
     76      * Set the metadata for this incident report.
     77      */
     78     void setMetadata(const IncidentMetadata& metadata);
     79 
     80     /*
     81      * Mark this incident report as finished and ready for broadcast.
     82      */
     83     void markCompleted();
     84 
     85     /*
     86      * Mark this incident report as finished and ready for broadcast.
     87      */
     88     status_t markApproved(const string& pkg, const string& cls);
     89 
     90     /**
     91      * Set the privacy policy that is being used to pre-filter the data
     92      * going to disk.
     93      */
     94     void setMaxPersistedPrivacyPolicy(int persistedPrivacyPolicy);
     95 
     96     /**
     97      * Save the metadata (envelope) information about the incident
     98      * report.  Must be called after addReport, setMetadata markCompleted
     99      * markApproved to save those changes to disk.
    100      */
    101     status_t saveEnvelope();
    102 
    103     /**
    104      * Like saveEnvelope() but will not clean up if there is an error.
    105      */
    106     status_t trySaveEnvelope();
    107 
    108     /**
    109      * Read the envelope information from disk.  If there was an error, the envelope and
    110      * data file will be removed.  If the proto can't be loaded, the whole file is deleted.
    111      */
    112     status_t loadEnvelope();
    113 
    114     /**
    115      * Like loadEnvelope() but will not clean up if there is an error.
    116      */
    117     status_t tryLoadEnvelope();
    118 
    119     /**
    120      * Get the envelope information.
    121      */
    122     const ReportFileProto& getEnvelope();
    123 
    124     /**
    125      * Open the file that will contain the contents of the incident report.  Call
    126      * close() or closeDataFile() on the result of getDataFileFd() when you're done.
    127      * This is not done automatically in the desctructor.   If there is an error, returns
    128      * it and you will not get an fd.
    129      */
    130     status_t startWritingDataFile();
    131 
    132     /**
    133      * Close the data file.
    134      */
    135     void closeDataFile();
    136 
    137     /**
    138      * Use the privacy and section configuration from the args parameter to filter data, write
    139      * to [writeFd] and take the ownership of [writeFd].
    140      *
    141      * Note: this call is blocking. When the writeFd is a pipe fd for IPC, caller should make sure
    142      * it's called on a separate thread so that reader can start to read without waiting for writer
    143      * to finish writing (which may not happen due to pipe buffer overflow).
    144      */
    145     status_t startFilteringData(int writeFd, const IncidentReportArgs& args);
    146 
    147     /**
    148      * Get the name of the data file on disk.
    149      */
    150     string getDataFileName() const;
    151 
    152     /**
    153      * Get the name of the envelope file on disk.
    154      */
    155     string getEnvelopeFileName() const;
    156 
    157     /**
    158      * Return the file descriptor for the data file, or -1 if it is not
    159      * currently open.
    160      */
    161     int getDataFileFd();
    162 
    163     /**
    164      * Record that there was an error writing to the data file.
    165      */
    166     void setWriteError(status_t err);
    167 
    168     /**
    169      * Get whether there was previously an error writing to the data file.
    170      */
    171     status_t getWriteError();
    172 
    173     /**
    174      * Get the unique identifier for this file.
    175      */
    176     string getId();
    177 
    178 private:
    179     sp<WorkDirectory> mWorkDirectory;
    180     int64_t mTimestampNs;
    181     string mEnvelopeFileName;
    182     string mDataFileName;
    183     ReportFileProto mEnvelope;
    184     int mDataFd;
    185     status_t mError;
    186 
    187     status_t save_envelope_impl(bool cleanup);
    188     status_t load_envelope_impl(bool cleanup);
    189 };
    190 
    191 /**
    192  * For directory cleanup to work, WorkDirectory must be kept
    193  * alive for the duration of all of the ReportFiles.  In the real
    194  * incidentd, WorkDirectory is a singleton.  In tests, it may
    195  * have a shorter duration.
    196  */
    197 class WorkDirectory : public virtual RefBase {
    198 public:
    199     /**
    200      * Save files to the default location.
    201      */
    202     WorkDirectory();
    203 
    204     /**
    205      * Save files to a specific location (primarily for testing).
    206      */
    207     WorkDirectory(const string& dir, int maxFileCount, long maxDiskUsageBytes);
    208 
    209     /**
    210      * Return a new report file.  Creating this object won't fail, but
    211      * subsequent actions on the file could, if the disk is full, permissions
    212      * aren't set correctly, etc.
    213      */
    214     sp<ReportFile> createReportFile();
    215 
    216     /**
    217      * Get the reports that are saved on-disk, with the time after (>) than the
    218      * given timestamp.  Pass 0 to start at the beginning.  These files
    219      * will be sorted by timestamp.  The envelope will not have been loaded.
    220      */
    221     status_t getReports(vector<sp<ReportFile>>* files, int64_t after);
    222 
    223     /**
    224      * Get the report with the given package, class and id. Returns nullptr if
    225      * that can't be found.  The envelope will have been loaded.  Returns the
    226      * original IncidentReportArgs in *args if args != nullptr.
    227      */
    228     sp<ReportFile> getReport(const string& pkg, const string& cls, const string& id,
    229             IncidentReportArgs* args);
    230 
    231     /**
    232      * Returns whether there are more reports after the given timestamp.
    233      */
    234     bool hasMore(int64_t after);
    235 
    236     /**
    237      * Confirm that a particular broadcast receiver has received the data.  When all
    238      * broadcast receivers for a particular report file have finished, the envelope
    239      * and data files will be deleted.
    240      */
    241     void commit(const sp<ReportFile>& report, const string& pkg, const string& cls);
    242 
    243     /**
    244      * Commit all reports the given package.
    245      */
    246     void commitAll(const string& pkg);
    247 
    248     /**
    249      * Remove the envelope and data file from disk, regardless of whether there are
    250      * more pending readers or broadcasts, for example in response to an error.
    251      */
    252     void remove(const sp<ReportFile>& report);
    253 
    254 private:
    255     string mDirectory;
    256     int mMaxFileCount;
    257     long mMaxDiskUsageBytes;
    258 
    259     // Held while creating or removing envelope files, which are the file that keeps
    260     // the directory consistent.
    261     mutex mLock;
    262 
    263     int64_t make_timestamp_ns_locked();
    264     bool file_exists_locked(int64_t timestampNs);
    265     off_t get_directory_contents_locked(map<string,WorkDirectoryEntry>* files, int64_t after);
    266     void clean_directory_locked();
    267     void delete_files_for_report_if_necessary(const sp<ReportFile>& report);
    268 
    269     string make_filename(int64_t timestampNs, const string& extension);
    270 };
    271 
    272 
    273 }  // namespace incidentd
    274 }  // namespace os
    275 }  // namespace android
    276 
    277