1342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn/*
2342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn * Copyright (C) 2017 The Android Open Source Project
3342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn *
4342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn * you may not use this file except in compliance with the License.
6342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn * You may obtain a copy of the License at
7342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn *
8342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn *
10342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn * Unless required by applicable law or agreed to in writing, software
11342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn * See the License for the specific language governing permissions and
14342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn * limitations under the License
15342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn */
16342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
17342e6037109a53830277d8de6ecf0e39578c143cDianne Hackbornpackage com.android.server.job;
18342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
19342e6037109a53830277d8de6ecf0e39578c143cDianne Hackbornimport android.app.IActivityManager;
20342e6037109a53830277d8de6ecf0e39578c143cDianne Hackbornimport android.content.ClipData;
21342e6037109a53830277d8de6ecf0e39578c143cDianne Hackbornimport android.content.ContentProvider;
22342e6037109a53830277d8de6ecf0e39578c143cDianne Hackbornimport android.content.Intent;
23342e6037109a53830277d8de6ecf0e39578c143cDianne Hackbornimport android.net.Uri;
24342e6037109a53830277d8de6ecf0e39578c143cDianne Hackbornimport android.os.IBinder;
25342e6037109a53830277d8de6ecf0e39578c143cDianne Hackbornimport android.os.RemoteException;
26342e6037109a53830277d8de6ecf0e39578c143cDianne Hackbornimport android.os.UserHandle;
27342e6037109a53830277d8de6ecf0e39578c143cDianne Hackbornimport android.util.Slog;
28342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
29342e6037109a53830277d8de6ecf0e39578c143cDianne Hackbornimport java.io.PrintWriter;
30342e6037109a53830277d8de6ecf0e39578c143cDianne Hackbornimport java.util.ArrayList;
31342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
326466c1cc5efc4ff05fabdd670cf78a6a7ca45afbDianne Hackbornpublic final class GrantedUriPermissions {
33342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    private final int mGrantFlags;
34342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    private final int mSourceUserId;
35342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    private final String mTag;
36342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    private final IBinder mPermissionOwner;
37342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    private final ArrayList<Uri> mUris = new ArrayList<>();
38342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
39342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    private GrantedUriPermissions(IActivityManager am, int grantFlags, int uid, String tag)
40342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            throws RemoteException {
41342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        mGrantFlags = grantFlags;
42342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        mSourceUserId = UserHandle.getUserId(uid);
43342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        mTag = tag;
44342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        mPermissionOwner = am.newUriPermissionOwner("job: " + tag);
45342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    }
46342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
47342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    public void revoke(IActivityManager am) {
48342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        for (int i = mUris.size()-1; i >= 0; i--) {
49342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            try {
50342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn                am.revokeUriPermissionFromOwner(mPermissionOwner, mUris.get(i),
51342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn                        mGrantFlags, mSourceUserId);
52342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            } catch (RemoteException e) {
53342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            }
54342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        }
55342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        mUris.clear();
56342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    }
57342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
58342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    public static boolean checkGrantFlags(int grantFlags) {
59342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        return (grantFlags & (Intent.FLAG_GRANT_WRITE_URI_PERMISSION
60342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn                |Intent.FLAG_GRANT_READ_URI_PERMISSION)) != 0;
61342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    }
62342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
63342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    public static GrantedUriPermissions createFromIntent(IActivityManager am, Intent intent,
64342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            int sourceUid, String targetPackage, int targetUserId, String tag) {
65342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        int grantFlags = intent.getFlags();
66342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        if (!checkGrantFlags(grantFlags)) {
67342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            return null;
68342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        }
69342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
70342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        GrantedUriPermissions perms = null;
71342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
72342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        Uri data = intent.getData();
73342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        if (data != null) {
74342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            perms = grantUri(am, data, sourceUid, targetPackage, targetUserId, grantFlags, tag,
75342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn                    perms);
76342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        }
77342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
78342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        ClipData clip = intent.getClipData();
79342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        if (clip != null) {
80342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags, tag,
81342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn                    perms);
82342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        }
83342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
84342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        return perms;
85342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    }
86342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
87342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    public static GrantedUriPermissions createFromClip(IActivityManager am, ClipData clip,
88342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag) {
89342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        if (!checkGrantFlags(grantFlags)) {
90342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            return null;
91342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        }
92342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        GrantedUriPermissions perms = null;
93342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        if (clip != null) {
94342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags,
95342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn                    tag, perms);
96342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        }
97342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        return perms;
98342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    }
99342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
100342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    private static GrantedUriPermissions grantClip(IActivityManager am, ClipData clip,
101342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag,
102342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            GrantedUriPermissions curPerms) {
103342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        final int N = clip.getItemCount();
104342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        for (int i = 0; i < N; i++) {
105342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            curPerms = grantItem(am, clip.getItemAt(i), sourceUid, targetPackage, targetUserId,
106342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn                    grantFlags, tag, curPerms);
107342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        }
108342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        return curPerms;
109342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    }
110342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
111342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    private static GrantedUriPermissions grantUri(IActivityManager am, Uri uri,
112342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag,
113342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            GrantedUriPermissions curPerms) {
114342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        try {
115342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            int sourceUserId = ContentProvider.getUserIdFromUri(uri,
116342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn                    UserHandle.getUserId(sourceUid));
117342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            uri = ContentProvider.getUriWithoutUserId(uri);
118342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            if (curPerms == null) {
119342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn                curPerms = new GrantedUriPermissions(am, grantFlags, sourceUid, tag);
120342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            }
121342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            am.grantUriPermissionFromOwner(curPerms.mPermissionOwner, sourceUid, targetPackage,
122342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn                    uri, grantFlags, sourceUserId, targetUserId);
123342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            curPerms.mUris.add(uri);
124342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        } catch (RemoteException e) {
125342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            Slog.e("JobScheduler", "AM dead");
126342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        }
127342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        return curPerms;
128342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    }
129342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
130342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    private static GrantedUriPermissions grantItem(IActivityManager am, ClipData.Item item,
131342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag,
132342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            GrantedUriPermissions curPerms) {
133342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        if (item.getUri() != null) {
134342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            curPerms = grantUri(am, item.getUri(), sourceUid, targetPackage, targetUserId,
135342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn                    grantFlags, tag, curPerms);
136342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        }
137342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        Intent intent = item.getIntent();
138342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        if (intent != null && intent.getData() != null) {
139342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            curPerms = grantUri(am, intent.getData(), sourceUid, targetPackage, targetUserId,
140342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn                    grantFlags, tag, curPerms);
141342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        }
142342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        return curPerms;
143342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    }
144342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn
145342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    // Dumpsys infrastructure
146342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    public void dump(PrintWriter pw, String prefix) {
147342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        pw.print(prefix); pw.print("mGrantFlags=0x"); pw.print(Integer.toHexString(mGrantFlags));
148342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        pw.print(" mSourceUserId="); pw.println(mSourceUserId);
149342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        pw.print(prefix); pw.print("mTag="); pw.println(mTag);
150342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        pw.print(prefix); pw.print("mPermissionOwner="); pw.println(mPermissionOwner);
151342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        for (int i = 0; i < mUris.size(); i++) {
152342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            pw.print(prefix); pw.print("#"); pw.print(i); pw.print(": ");
153342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn            pw.println(mUris.get(i));
154342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn        }
155342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn    }
156342e6037109a53830277d8de6ecf0e39578c143cDianne Hackborn}
157