Home | History | Annotate | Download | only in slice
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
      5  * except in compliance with the License. You may obtain a copy of the License at
      6  *
      7  *      http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software distributed under the
     10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     11  * KIND, either express or implied. See the License for the specific language governing
     12  * permissions and limitations under the License.
     13  */
     14 
     15 package com.android.server.slice;
     16 
     17 import android.annotation.NonNull;
     18 import android.util.ArrayMap;
     19 import android.util.ArraySet;
     20 import android.util.Slog;
     21 
     22 import com.android.server.slice.DirtyTracker.Persistable;
     23 import com.android.server.slice.SlicePermissionManager.PkgUser;
     24 
     25 import org.xmlpull.v1.XmlPullParser;
     26 import org.xmlpull.v1.XmlPullParserException;
     27 import org.xmlpull.v1.XmlSerializer;
     28 
     29 import java.io.IOException;
     30 import java.util.ArrayList;
     31 import java.util.Collection;
     32 import java.util.Objects;
     33 
     34 public class SliceProviderPermissions implements DirtyTracker, Persistable {
     35 
     36     private static final String TAG = "SliceProviderPermissions";
     37 
     38     static final String TAG_PROVIDER = "provider";
     39     private static final String TAG_AUTHORITY = "authority";
     40     private static final String TAG_PKG = "pkg";
     41     private static final String NAMESPACE = null;
     42 
     43     private static final String ATTR_PKG = "pkg";
     44     private static final String ATTR_AUTHORITY = "authority";
     45 
     46     private final PkgUser mPkg;
     47     private final ArrayMap<String, SliceAuthority> mAuths = new ArrayMap<>();
     48     private final DirtyTracker mTracker;
     49 
     50     public SliceProviderPermissions(@NonNull PkgUser pkg, @NonNull DirtyTracker tracker) {
     51         mPkg = pkg;
     52         mTracker = tracker;
     53     }
     54 
     55     public PkgUser getPkg() {
     56         return mPkg;
     57     }
     58 
     59     public synchronized Collection<SliceAuthority> getAuthorities() {
     60         return new ArrayList<>(mAuths.values());
     61     }
     62 
     63     public synchronized SliceAuthority getOrCreateAuthority(String authority) {
     64         SliceAuthority ret = mAuths.get(authority);
     65         if (ret == null) {
     66             ret = new SliceAuthority(authority, this);
     67             mAuths.put(authority, ret);
     68             onPersistableDirty(ret);
     69         }
     70         return ret;
     71     }
     72 
     73     @Override
     74     public void onPersistableDirty(Persistable obj) {
     75         mTracker.onPersistableDirty(this);
     76     }
     77 
     78     @Override
     79     public String getFileName() {
     80         return getFileName(mPkg);
     81     }
     82 
     83     public synchronized void writeTo(XmlSerializer out) throws IOException {
     84         out.startTag(NAMESPACE, TAG_PROVIDER);
     85         out.attribute(NAMESPACE, ATTR_PKG, mPkg.toString());
     86 
     87         final int N = mAuths.size();
     88         for (int i = 0; i < N; i++) {
     89             out.startTag(NAMESPACE, TAG_AUTHORITY);
     90             out.attribute(NAMESPACE, ATTR_AUTHORITY, mAuths.valueAt(i).mAuthority);
     91 
     92             mAuths.valueAt(i).writeTo(out);
     93 
     94             out.endTag(NAMESPACE, TAG_AUTHORITY);
     95         }
     96 
     97         out.endTag(NAMESPACE, TAG_PROVIDER);
     98     }
     99 
    100     public static SliceProviderPermissions createFrom(XmlPullParser parser, DirtyTracker tracker)
    101             throws XmlPullParserException, IOException {
    102         // Get to the beginning of the provider.
    103         while (parser.getEventType() != XmlPullParser.START_TAG
    104                 || !TAG_PROVIDER.equals(parser.getName())) {
    105             parser.next();
    106         }
    107         int depth = parser.getDepth();
    108         PkgUser pkgUser = new PkgUser(parser.getAttributeValue(NAMESPACE, ATTR_PKG));
    109         SliceProviderPermissions provider = new SliceProviderPermissions(pkgUser, tracker);
    110         parser.next();
    111 
    112         while (parser.getDepth() > depth) {
    113             if (parser.getEventType() == XmlPullParser.START_TAG
    114                     && TAG_AUTHORITY.equals(parser.getName())) {
    115                 try {
    116                     SliceAuthority authority = new SliceAuthority(
    117                             parser.getAttributeValue(NAMESPACE, ATTR_AUTHORITY), provider);
    118                     authority.readFrom(parser);
    119                     provider.mAuths.put(authority.getAuthority(), authority);
    120                 } catch (IllegalArgumentException e) {
    121                     Slog.e(TAG, "Couldn't read PkgUser", e);
    122                 }
    123             }
    124 
    125             parser.next();
    126         }
    127         return provider;
    128     }
    129 
    130     public static String getFileName(PkgUser pkg) {
    131         return String.format("provider_%s", pkg.toString());
    132     }
    133 
    134     public static class SliceAuthority implements Persistable {
    135         private final String mAuthority;
    136         private final DirtyTracker mTracker;
    137         private final ArraySet<PkgUser> mPkgs = new ArraySet<>();
    138 
    139         public SliceAuthority(String authority, DirtyTracker tracker) {
    140             mAuthority = authority;
    141             mTracker = tracker;
    142         }
    143 
    144         public String getAuthority() {
    145             return mAuthority;
    146         }
    147 
    148         public synchronized void addPkg(PkgUser pkg) {
    149             if (mPkgs.add(pkg)) {
    150                 mTracker.onPersistableDirty(this);
    151             }
    152         }
    153 
    154         public synchronized void removePkg(PkgUser pkg) {
    155             if (mPkgs.remove(pkg)) {
    156                 mTracker.onPersistableDirty(this);
    157             }
    158         }
    159 
    160         public synchronized Collection<PkgUser> getPkgs() {
    161             return new ArraySet<>(mPkgs);
    162         }
    163 
    164         @Override
    165         public String getFileName() {
    166             return null;
    167         }
    168 
    169         public synchronized void writeTo(XmlSerializer out) throws IOException {
    170             final int N = mPkgs.size();
    171             for (int i = 0; i < N; i++) {
    172                 out.startTag(NAMESPACE, TAG_PKG);
    173                 out.text(mPkgs.valueAt(i).toString());
    174                 out.endTag(NAMESPACE, TAG_PKG);
    175             }
    176         }
    177 
    178         public synchronized void readFrom(XmlPullParser parser)
    179                 throws IOException, XmlPullParserException {
    180             parser.next();
    181             int depth = parser.getDepth();
    182             while (parser.getDepth() >= depth) {
    183                 if (parser.getEventType() == XmlPullParser.START_TAG
    184                         && TAG_PKG.equals(parser.getName())) {
    185                     mPkgs.add(new PkgUser(parser.nextText()));
    186                 }
    187                 parser.next();
    188             }
    189         }
    190 
    191         @Override
    192         public boolean equals(Object obj) {
    193             if (!getClass().equals(obj != null ? obj.getClass() : null)) return false;
    194             SliceAuthority other = (SliceAuthority) obj;
    195             return Objects.equals(mAuthority, other.mAuthority)
    196                     && Objects.equals(mPkgs, other.mPkgs);
    197         }
    198 
    199         @Override
    200         public String toString() {
    201             return String.format("(%s: %s)", mAuthority, mPkgs.toString());
    202         }
    203     }
    204 }
    205