/*
 * Copyright (C) 2018 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.
 */

#pragma once

#include <sys/types.h>

#include <string>
#include <vector>

#include "meminfo.h"

namespace android {
namespace meminfo {

using VmaCallback = std::function<void(const Vma&)>;

class ProcMemInfo final {
    // Per-process memory accounting
  public:
    // Reset the working set accounting of the process via /proc/<pid>/clear_refs
    static bool ResetWorkingSet(pid_t pid);

    ProcMemInfo(pid_t pid, bool get_wss = false, uint64_t pgflags = 0, uint64_t pgflags_mask = 0);

    const std::vector<Vma>& Maps();
    const MemUsage& Usage();
    const MemUsage& Wss();

    // Same as Maps() except, only valid for reading working set using CONFIG_IDLE_PAGE_TRACKING
    // support in kernel. If the kernel support doesn't exist, the function will return an empty
    // vector.
    const std::vector<Vma>& MapsWithPageIdle();

    // Collect all 'vma' or 'maps' from /proc/<pid>/smaps and store them in 'maps_'. Returns a
    // constant reference to the vma vector after the collection is done.
    //
    // Each 'struct Vma' is *fully* populated by this method (unlike SmapsOrRollup).
    const std::vector<Vma>& Smaps(const std::string& path = "");

    // This method reads /proc/<pid>/smaps and calls the callback() for each
    // vma or map that it finds. The map is converted to 'struct Vma' object which is then
    // passed to the callback.
    // Returns 'false' if the file is malformed.
    bool ForEachVma(const VmaCallback& callback);

    // Used to parse either of /proc/<pid>/{smaps, smaps_rollup} and record the process's
    // Pss and Private memory usage in 'stats'.  In particular, the method only populates the fields
    // of the MemUsage structure that are intended to be used by Android's periodic Pss collection.
    //
    // The method populates the following statistics in order to be fast an efficient.
    //   Pss
    //   Rss
    //   Uss
    //   private_clean
    //   private_dirty
    //   SwapPss
    // All other fields of MemUsage are zeroed.
    bool SmapsOrRollup(MemUsage* stats) const;

    // Used to parse either of /proc/<pid>/{smaps, smaps_rollup} and record the process's
    // Pss.
    // Returns 'true' on success and the value of Pss in the out parameter.
    bool SmapsOrRollupPss(uint64_t* pss) const;

    const std::vector<uint16_t>& SwapOffsets();

    // Reads /proc/<pid>/pagemap for this process for each page within
    // the 'vma' and stores that in 'pagemap'. It is assumed that the 'vma'
    // is obtained by calling Maps() or 'ForEachVma' for the same object. No special checks
    // are made to see if 'vma' is *valid*.
    // Returns false if anything goes wrong, 'true' otherwise.
    bool PageMap(const Vma& vma, std::vector<uint64_t>* pagemap);

    ~ProcMemInfo() = default;

  private:
    bool ReadMaps(bool get_wss, bool use_pageidle = false);
    bool ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_pageidle);

    pid_t pid_;
    bool get_wss_;
    uint64_t pgflags_;
    uint64_t pgflags_mask_;

    std::vector<Vma> maps_;

    MemUsage usage_;
    std::vector<uint16_t> swap_offsets_;
};

// Makes callback for each 'vma' or 'map' found in file provided. The file is expected to be in the
// same format as /proc/<pid>/smaps. Returns 'false' if the file is malformed.
bool ForEachVmaFromFile(const std::string& path, const VmaCallback& callback);

// Returns if the kernel supports /proc/<pid>/smaps_rollup. Assumes that the
// calling process has access to the /proc/<pid>/smaps_rollup.
// Returns 'false' if the calling process has no permission to read the file if it exists
// of if the file doesn't exist.
bool IsSmapsRollupSupported(pid_t pid);

// Same as ProcMemInfo::SmapsOrRollup but reads the statistics directly
// from a file. The file MUST be in the same format as /proc/<pid>/smaps
// or /proc/<pid>/smaps_rollup
bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats);

// Same as ProcMemInfo::SmapsOrRollupPss but reads the statistics directly
// from a file and returns total Pss in kB. The file MUST be in the same format
// as /proc/<pid>/smaps or /proc/<pid>/smaps_rollup
bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss);

}  // namespace meminfo
}  // namespace android
