content: /*
   * 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.
   */
  
  package com.android.server.slice;
  
  import android.content.Context;
  import android.content.pm.UserInfo;
  import android.os.UserHandle;
  import android.os.UserManager;
  import android.util.ArraySet;
  import android.util.SparseArray;
  
  import com.android.internal.util.XmlUtils;
  
  import org.xmlpull.v1.XmlPullParser;
  import org.xmlpull.v1.XmlPullParserException;
  import org.xmlpull.v1.XmlSerializer;
  
  import java.io.IOException;
  import java.util.List;
  
  public class SliceFullAccessList {
  
      static final int DB_VERSION = 1;
      private static final String TAG = "SliceFullAccessList";
  
      private static final String TAG_LIST = "slice-access-list";
      private static final String TAG_PKG = "pkg";
      private static final String TAG_USER = "user";
  
      private final String ATT_USER_ID = "user";
      private final String ATT_VERSION = "version";
  
      private final SparseArray<ArraySet<String>> mFullAccessPkgs = new SparseArray<>();
      private final Context mContext;
  
      public SliceFullAccessList(Context context) {
          mContext = context;
      }
  
      public boolean hasFullAccess(String pkg, int userId) {
          ArraySet<String> pkgs = mFullAccessPkgs.get(userId, null);
          return pkgs != null && pkgs.contains(pkg);
      }
  
      public void grantFullAccess(String pkg, int userId) {
          ArraySet<String> pkgs = mFullAccessPkgs.get(userId, null);
          if (pkgs == null) {
              pkgs = new ArraySet<>();
              mFullAccessPkgs.put(userId, pkgs);
          }
          pkgs.add(pkg);
      }
  
      public void removeGrant(String pkg, int userId) {
          ArraySet<String> pkgs = mFullAccessPkgs.get(userId, null);
          if (pkgs == null) {
              pkgs = new ArraySet<>();
              mFullAccessPkgs.put(userId, pkgs);
          }
          pkgs.remove(pkg);
      }
  
      public void writeXml(XmlSerializer out, int user) throws IOException {
          out.startTag(null, TAG_LIST);
          out.attribute(null, ATT_VERSION, String.valueOf(DB_VERSION));
  
          final int N = mFullAccessPkgs.size();
          for (int i = 0 ; i < N; i++) {
              final int userId = mFullAccessPkgs.keyAt(i);
              final ArraySet<String> pkgs = mFullAccessPkgs.valueAt(i);
              if (user != UserHandle.USER_ALL && user != userId) {
                  continue;
              }
              out.startTag(null, TAG_USER);
              out.attribute(null, ATT_USER_ID, Integer.toString(userId));
              if (pkgs != null) {
                  final int M = pkgs.size();
                  for (int j = 0; j < M; j++) {
                          out.startTag(null, TAG_PKG);
                          out.text(pkgs.valueAt(j));
                          out.endTag(null, TAG_PKG);
                  }
              }
              out.endTag(null, TAG_USER);
          }
          out.endTag(null, TAG_LIST);
      }
  
      public void readXml(XmlPullParser parser) throws XmlPullParserException, IOException {
          // upgrade xml
          int xmlVersion = XmlUtils.readIntAttribute(parser, ATT_VERSION, 0);
          final List<UserInfo> activeUsers = UserManager.get(mContext).getUsers(true);
          for (UserInfo userInfo : activeUsers) {
              upgradeXml(xmlVersion, userInfo.getUserHandle().getIdentifier());
          }
  
          mFullAccessPkgs.clear();
          // read grants
          int type;
          while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
              String tag = parser.getName();
              if (type == XmlPullParser.END_TAG
                      && TAG_LIST.equals(tag)) {
                  break;
              }
              if (type == XmlPullParser.START_TAG) {
                  if (TAG_USER.equals(tag)) {
                      final int userId = XmlUtils.readIntAttribute(parser, ATT_USER_ID, 0);
                      ArraySet<String> pkgs = new ArraySet<>();
                      while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
                          String userTag = parser.getName();
                          if (type == XmlPullParser.END_TAG
                                  && TAG_USER.equals(userTag)) {
                              break;
                          }
                          if (type == XmlPullParser.START_TAG) {
                              if (TAG_PKG.equals(userTag)) {
                                  final String pkg = parser.nextText();
                                  pkgs.add(pkg);
                              }
                          }
                      }
                      mFullAccessPkgs.put(userId, pkgs);
                  }
              }
          }
      }
  
      protected void upgradeXml(final int xmlVersion, final int userId) {}
  }
  