1/*
2 * Copyright (C) 2010 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
17package com.android.server.am;
18
19import android.content.Intent;
20import android.net.Uri;
21import android.os.Binder;
22import android.os.IBinder;
23
24import java.util.HashSet;
25import java.util.Iterator;
26
27class UriPermissionOwner {
28    final ActivityManagerService service;
29    final Object owner;
30
31    Binder externalToken;
32
33    HashSet<UriPermission> readUriPermissions; // special access to reading uris.
34    HashSet<UriPermission> writeUriPermissions; // special access to writing uris.
35
36    class ExternalToken extends Binder {
37        UriPermissionOwner getOwner() {
38            return UriPermissionOwner.this;
39        }
40    }
41
42    UriPermissionOwner(ActivityManagerService _service, Object _owner) {
43        service = _service;
44        owner = _owner;
45    }
46
47    Binder getExternalTokenLocked() {
48        if (externalToken == null) {
49            externalToken = new ExternalToken();
50        }
51        return externalToken;
52    }
53
54    static UriPermissionOwner fromExternalToken(IBinder token) {
55        if (token instanceof ExternalToken) {
56            return ((ExternalToken)token).getOwner();
57        }
58        return null;
59    }
60
61    void removeUriPermissionsLocked() {
62        removeUriPermissionsLocked(Intent.FLAG_GRANT_READ_URI_PERMISSION
63                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
64    }
65
66    void removeUriPermissionsLocked(int mode) {
67        if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
68                && readUriPermissions != null) {
69            for (UriPermission perm : readUriPermissions) {
70                perm.readOwners.remove(this);
71                if (perm.readOwners.size() == 0 && (perm.globalModeFlags
72                        &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
73                    perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
74                    service.removeUriPermissionIfNeededLocked(perm);
75                }
76            }
77            readUriPermissions = null;
78        }
79        if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
80                && writeUriPermissions != null) {
81            for (UriPermission perm : writeUriPermissions) {
82                perm.writeOwners.remove(this);
83                if (perm.writeOwners.size() == 0 && (perm.globalModeFlags
84                        &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
85                    perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
86                    service.removeUriPermissionIfNeededLocked(perm);
87                }
88            }
89            writeUriPermissions = null;
90        }
91    }
92
93    void removeUriPermissionLocked(Uri uri, int mode) {
94        if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
95                && readUriPermissions != null) {
96            Iterator<UriPermission> it = readUriPermissions.iterator();
97            while (it.hasNext()) {
98                UriPermission perm = it.next();
99                if (uri.equals(perm.uri)) {
100                    perm.readOwners.remove(this);
101                    if (perm.readOwners.size() == 0 && (perm.globalModeFlags
102                            &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
103                        perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
104                        service.removeUriPermissionIfNeededLocked(perm);
105                    }
106                    it.remove();
107                }
108            }
109            if (readUriPermissions.size() == 0) {
110                readUriPermissions = null;
111            }
112        }
113        if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
114                && writeUriPermissions != null) {
115            Iterator<UriPermission> it = writeUriPermissions.iterator();
116            while (it.hasNext()) {
117                UriPermission perm = it.next();
118                if (uri.equals(perm.uri)) {
119                    perm.writeOwners.remove(this);
120                    if (perm.writeOwners.size() == 0 && (perm.globalModeFlags
121                            &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
122                        perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
123                        service.removeUriPermissionIfNeededLocked(perm);
124                    }
125                    it.remove();
126                }
127            }
128            if (writeUriPermissions.size() == 0) {
129                writeUriPermissions = null;
130            }
131        }
132    }
133
134    public void addReadPermission(UriPermission perm) {
135        if (readUriPermissions == null) {
136            readUriPermissions = new HashSet<UriPermission>();
137        }
138        readUriPermissions.add(perm);
139    }
140
141    public void addWritePermission(UriPermission perm) {
142        if (writeUriPermissions == null) {
143            writeUriPermissions = new HashSet<UriPermission>();
144        }
145        writeUriPermissions.add(perm);
146    }
147
148    public void removeReadPermission(UriPermission perm) {
149        readUriPermissions.remove(perm);
150        if (readUriPermissions.size() == 0) {
151            readUriPermissions = null;
152        }
153    }
154
155    public void removeWritePermission(UriPermission perm) {
156        writeUriPermissions.remove(perm);
157        if (writeUriPermissions.size() == 0) {
158            writeUriPermissions = null;
159        }
160    }
161
162    @Override
163    public String toString() {
164        return owner.toString();
165    }
166}
167