ClipboardService.java revision ad70bc6c310f54d4810e67b49e7881c1f33a1d83
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1730f8eb472e44228069c2ffb8bd0b43213edbf04eAmith Yamasanipackage com.android.server.clipboard;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.app.ActivityManagerNative;
20ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tateimport android.app.AppGlobals;
21efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackbornimport android.app.AppOpsManager;
2290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.app.IActivityManager;
231040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackbornimport android.content.ClipData;
241040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackbornimport android.content.ClipDescription;
25d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevotimport android.content.ContentProvider;
269f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.content.IClipboard;
279f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.content.IOnPrimaryClipChangedListener;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
2990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.content.Intent;
30ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tateimport android.content.pm.IPackageManager;
3190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.content.pm.PackageInfo;
3290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.content.pm.PackageManager;
33f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevotimport android.content.pm.UserInfo;
3490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.net.Uri;
3590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.os.Binder;
3690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.os.IBinder;
37f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevotimport android.os.IUserManager;
3890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.os.Parcel;
3990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.os.Process;
409f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.os.RemoteCallbackList;
419f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.os.RemoteException;
42f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevotimport android.os.ServiceManager;
43f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle;
44f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevotimport android.os.UserManager;
4590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.util.Slog;
46e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasaniimport android.util.SparseArray;
4790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
48ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shankaimport com.android.server.SystemService;
49ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka
5090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport java.util.HashSet;
51f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevotimport java.util.List;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Implementation of the clipboard for copy and paste.
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
56ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shankapublic class ClipboardService extends SystemService {
57e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
58e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    private static final String TAG = "ClipboardService";
59e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
6090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final IActivityManager mAm;
61f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    private final IUserManager mUm;
6290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final PackageManager mPm;
63efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn    private final AppOpsManager mAppOps;
6490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final IBinder mPermissionOwner;
6590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
66ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka    private final SparseArray<PerUserClipboard> mClipboards = new SparseArray<>();
67ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka
68ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka    /**
69ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka     * Instantiates the clipboard.
70ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka     */
71ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka    public ClipboardService(Context context) {
72ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        super(context);
73ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka
74ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        mAm = ActivityManagerNative.getDefault();
75ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        mPm = getContext().getPackageManager();
76ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
77ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
78ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        IBinder permOwner = null;
79ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        try {
80ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            permOwner = mAm.newUriPermissionOwner("clipboard");
81ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        } catch (RemoteException e) {
82ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            Slog.w("clipboard", "AM dead", e);
83ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        }
84ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        mPermissionOwner = permOwner;
85ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka    }
86ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka
87ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka    @Override
88ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka    public void onStart() {
89ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        publishBinderService(Context.CLIPBOARD_SERVICE, new ClipboardImpl());
90ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka    }
91ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka
92ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka    @Override
93ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka    public void onCleanupUser(int userId) {
94ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        synchronized (mClipboards) {
95ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            mClipboards.remove(userId);
96ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        }
97ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka    }
98ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka
99efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn    private class ListenerInfo {
100efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn        final int mUid;
101efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn        final String mPackageName;
102efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn        ListenerInfo(int uid, String packageName) {
103efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            mUid = uid;
104efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            mPackageName = packageName;
105efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn        }
106efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn    }
107efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn
108e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    private class PerUserClipboard {
109e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        final int userId;
110e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
111e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        final RemoteCallbackList<IOnPrimaryClipChangedListener> primaryClipListeners
112e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                = new RemoteCallbackList<IOnPrimaryClipChangedListener>();
113e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
114e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        ClipData primaryClip;
115e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
116e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        final HashSet<String> activePermissionOwners
117e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                = new HashSet<String>();
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
119e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        PerUserClipboard(int userId) {
120e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            this.userId = userId;
121e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        }
122e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    }
12390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
124ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka    private class ClipboardImpl extends IClipboard.Stub {
125ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        @Override
126ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
127ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                throws RemoteException {
128ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            try {
129ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                return super.onTransact(code, data, reply, flags);
130ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            } catch (RuntimeException e) {
131ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                if (!(e instanceof SecurityException)) {
132ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                    Slog.wtf("clipboard", "Exception: ", e);
133ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                }
134ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                throw e;
135ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            }
13690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
13790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
138e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
139ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        @Override
140ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        public void setPrimaryClip(ClipData clip, String callingPackage) {
141ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            synchronized (this) {
142ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                if (clip != null && clip.getItemCount() <= 0) {
143ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                    throw new IllegalArgumentException("No items");
144ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                }
145ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                final int callingUid = Binder.getCallingUid();
146ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                if (mAppOps.noteOp(AppOpsManager.OP_WRITE_CLIPBOARD, callingUid,
147ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        callingPackage) != AppOpsManager.MODE_ALLOWED) {
148ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                    return;
149ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                }
150ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                checkDataOwnerLocked(clip, callingUid);
151ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                final int userId = UserHandle.getUserId(callingUid);
152ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                PerUserClipboard clipboard = getClipboard(userId);
153ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                revokeUris(clipboard);
154ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                setPrimaryClipInternal(clipboard, clip);
155ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                List<UserInfo> related = getRelatedProfiles(userId);
156ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                if (related != null) {
157ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                    int size = related.size();
158ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                    if (size > 1) { // Related profiles list include the current profile.
159ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        boolean canCopy = false;
160ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        try {
161ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            canCopy = !mUm.getUserRestrictions(userId).getBoolean(
162ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                                    UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
163ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        } catch (RemoteException e) {
164ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            Slog.e(TAG, "Remote Exception calling UserManager: " + e);
165ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        }
166ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        // Copy clip data to related users if allowed. If disallowed, then remove
167ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        // primary clip in related users to prevent pasting stale content.
168ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        if (!canCopy) {
169ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            clip = null;
170ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        } else {
171ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            // We want to fix the uris of the related user's clip without changing the
172ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            // uris of the current user's clip.
173ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            // So, copy the ClipData, and then copy all the items, so that nothing
174ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            // is shared in memmory.
175ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            clip = new ClipData(clip);
176ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            for (int i = clip.getItemCount() - 1; i >= 0; i--) {
177ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                                clip.setItemAt(i, new ClipData.Item(clip.getItemAt(i)));
178ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            }
179ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            clip.fixUrisLight(userId);
180ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        }
181ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        for (int i = 0; i < size; i++) {
182ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            int id = related.get(i).id;
183ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            if (id != userId) {
184ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                                setPrimaryClipInternal(getClipboard(id), clip);
185ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                            }
186ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        }
187ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                    }
188ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                }
189ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            }
190ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        }
191ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka
192ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        @Override
193ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        public ClipData getPrimaryClip(String pkg) {
194ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            synchronized (this) {
195ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                if (mAppOps.noteOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
196ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        pkg) != AppOpsManager.MODE_ALLOWED) {
197ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                    return null;
198e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                }
199ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                addActiveOwnerLocked(Binder.getCallingUid(), pkg);
200ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                return getClipboard().primaryClip;
201e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            }
202ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        }
20390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
204ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        @Override
205ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        public ClipDescription getPrimaryClipDescription(String callingPackage) {
206ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            synchronized (this) {
207ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
208ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        callingPackage) != AppOpsManager.MODE_ALLOWED) {
209ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                    return null;
210ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                }
211ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                PerUserClipboard clipboard = getClipboard();
212ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                return clipboard.primaryClip != null ? clipboard.primaryClip.getDescription() : null;
213164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn            }
21490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
215ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka
216ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        @Override
217ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        public boolean hasPrimaryClip(String callingPackage) {
218ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            synchronized (this) {
219ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
220ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        callingPackage) != AppOpsManager.MODE_ALLOWED) {
221ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                    return false;
222ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                }
223ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                return getClipboard().primaryClip != null;
224ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            }
225ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        }
226ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka
227ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        @Override
228ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        public void addPrimaryClipChangedListener(IOnPrimaryClipChangedListener listener,
229ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                String callingPackage) {
230ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            synchronized (this) {
231ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                getClipboard().primaryClipListeners.register(listener,
232ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        new ListenerInfo(Binder.getCallingUid(), callingPackage));
233ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            }
234ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        }
235ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka
236ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        @Override
237ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        public void removePrimaryClipChangedListener(IOnPrimaryClipChangedListener listener) {
238ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            synchronized (this) {
239ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                getClipboard().primaryClipListeners.unregister(listener);
240ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            }
241ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        }
242ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka
243ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        @Override
244ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        public boolean hasClipboardText(String callingPackage) {
245ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            synchronized (this) {
246ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
247ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                        callingPackage) != AppOpsManager.MODE_ALLOWED) {
248ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                    return false;
249ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                }
250ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                PerUserClipboard clipboard = getClipboard();
251ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                if (clipboard.primaryClip != null) {
252ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                    CharSequence text = clipboard.primaryClip.getItemAt(0).getText();
253ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                    return text != null && text.length() > 0;
254ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                }
255ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka                return false;
256ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka            }
257ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka        }
258ad70bc6c310f54d4810e67b49e7881c1f33a1d83Sudheer Shanka    };
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
260e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    private PerUserClipboard getClipboard() {
261f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        return getClipboard(UserHandle.getCallingUserId());
262e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    }
263e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
264e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    private PerUserClipboard getClipboard(int userId) {
265e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        synchronized (mClipboards) {
266e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            PerUserClipboard puc = mClipboards.get(userId);
267e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            if (puc == null) {
268e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                puc = new PerUserClipboard(userId);
269e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                mClipboards.put(userId, puc);
270e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            }
271e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            return puc;
272e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        }
273e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    }
274e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
275f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    List<UserInfo> getRelatedProfiles(int userId) {
276f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        final List<UserInfo> related;
277f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        final long origId = Binder.clearCallingIdentity();
278f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        try {
279f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            related = mUm.getProfiles(userId, true);
280f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        } catch (RemoteException e) {
281f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            Slog.e(TAG, "Remote Exception calling UserManager: " + e);
282f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            return null;
283f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        } finally{
284f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            Binder.restoreCallingIdentity(origId);
285f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        }
286f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        return related;
287f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    }
288f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot
289f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    void setPrimaryClipInternal(PerUserClipboard clipboard, ClipData clip) {
290f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        clipboard.activePermissionOwners.clear();
291f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        if (clip == null && clipboard.primaryClip == null) {
292f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            return;
293f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        }
294f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        clipboard.primaryClip = clip;
295f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        final long ident = Binder.clearCallingIdentity();
296f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        final int n = clipboard.primaryClipListeners.beginBroadcast();
297f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        try {
298f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            for (int i = 0; i < n; i++) {
299f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                try {
300f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    ListenerInfo li = (ListenerInfo)
301f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                            clipboard.primaryClipListeners.getBroadcastCookie(i);
302f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    if (mAppOps.checkOpNoThrow(AppOpsManager.OP_READ_CLIPBOARD, li.mUid,
303f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                            li.mPackageName) == AppOpsManager.MODE_ALLOWED) {
304f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                        clipboard.primaryClipListeners.getBroadcastItem(i)
305f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                                .dispatchPrimaryClipChanged();
306efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                    }
307f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                } catch (RemoteException e) {
308f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    // The RemoteCallbackList will take care of removing
309f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    // the dead object for us.
3109f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                }
3119f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            }
312f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        } finally {
313f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            clipboard.primaryClipListeners.finishBroadcast();
314f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            Binder.restoreCallingIdentity(ident);
3159f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
3169f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
31790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
31890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final void checkUriOwnerLocked(Uri uri, int uid) {
31990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (!"content".equals(uri.getScheme())) {
32090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            return;
32190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
32290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        long ident = Binder.clearCallingIdentity();
32390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        try {
32490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            // This will throw SecurityException for us.
325d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot            mAm.checkGrantUriPermission(uid, null, ContentProvider.getUriWithoutUserId(uri),
326f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    Intent.FLAG_GRANT_READ_URI_PERMISSION,
327f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(uid)));
32890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } catch (RemoteException e) {
32990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } finally {
33090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            Binder.restoreCallingIdentity(ident);
33190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
33290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
33390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
33490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final void checkItemOwnerLocked(ClipData.Item item, int uid) {
33590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (item.getUri() != null) {
33690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            checkUriOwnerLocked(item.getUri(), uid);
33790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
33890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        Intent intent = item.getIntent();
33990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (intent != null && intent.getData() != null) {
34090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            checkUriOwnerLocked(intent.getData(), uid);
34190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
34290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
34390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
34490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final void checkDataOwnerLocked(ClipData data, int uid) {
34590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        final int N = data.getItemCount();
34690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        for (int i=0; i<N; i++) {
347327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn            checkItemOwnerLocked(data.getItemAt(i), uid);
34890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
34990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
35090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
351f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    private final void grantUriLocked(Uri uri, String pkg, int userId) {
35290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        long ident = Binder.clearCallingIdentity();
35390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        try {
354f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            int sourceUserId = ContentProvider.getUserIdFromUri(uri, userId);
355f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            uri = ContentProvider.getUriWithoutUserId(uri);
356d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot            mAm.grantUriPermissionFromOwner(mPermissionOwner, Process.myUid(), pkg,
357f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId, userId);
35890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } catch (RemoteException e) {
35990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } finally {
36090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            Binder.restoreCallingIdentity(ident);
36190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
36290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
36390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
364f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    private final void grantItemLocked(ClipData.Item item, String pkg, int userId) {
36590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (item.getUri() != null) {
366f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            grantUriLocked(item.getUri(), pkg, userId);
36790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
36890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        Intent intent = item.getIntent();
36990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (intent != null && intent.getData() != null) {
370f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            grantUriLocked(intent.getData(), pkg, userId);
37190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
37290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
37390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
37490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final void addActiveOwnerLocked(int uid, String pkg) {
375ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate        final IPackageManager pm = AppGlobals.getPackageManager();
376ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate        final int targetUserHandle = UserHandle.getCallingUserId();
377ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate        final long oldIdentity = Binder.clearCallingIdentity();
37890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        try {
379ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate            PackageInfo pi = pm.getPackageInfo(pkg, 0, targetUserHandle);
380ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate            if (pi == null) {
381ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate                throw new IllegalArgumentException("Unknown package " + pkg);
382ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate            }
383f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn            if (!UserHandle.isSameApp(pi.applicationInfo.uid, uid)) {
38490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn                throw new SecurityException("Calling uid " + uid
38590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn                        + " does not own package " + pkg);
38690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            }
387ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate        } catch (RemoteException e) {
388ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate            // Can't happen; the package manager is in the same process
389ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate        } finally {
390ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate            Binder.restoreCallingIdentity(oldIdentity);
39190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
392e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        PerUserClipboard clipboard = getClipboard();
393e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        if (clipboard.primaryClip != null && !clipboard.activePermissionOwners.contains(pkg)) {
394e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            final int N = clipboard.primaryClip.getItemCount();
39590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            for (int i=0; i<N; i++) {
396f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                grantItemLocked(clipboard.primaryClip.getItemAt(i), pkg, UserHandle.getUserId(uid));
39790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            }
398e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            clipboard.activePermissionOwners.add(pkg);
39990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
40090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
40190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
40290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final void revokeUriLocked(Uri uri) {
403f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        int userId = ContentProvider.getUserIdFromUri(uri,
404f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                UserHandle.getUserId(Binder.getCallingUid()));
40590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        long ident = Binder.clearCallingIdentity();
40690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        try {
407f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            uri = ContentProvider.getUriWithoutUserId(uri);
408f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            mAm.revokeUriPermissionFromOwner(mPermissionOwner, uri,
409d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot                    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
410f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    userId);
41190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } catch (RemoteException e) {
41290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } finally {
41390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            Binder.restoreCallingIdentity(ident);
41490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
41590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
41690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
41790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final void revokeItemLocked(ClipData.Item item) {
41890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (item.getUri() != null) {
41990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            revokeUriLocked(item.getUri());
42090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
42190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        Intent intent = item.getIntent();
42290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (intent != null && intent.getData() != null) {
42390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            revokeUriLocked(intent.getData());
42490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
42590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
42690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
427f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    private final void revokeUris(PerUserClipboard clipboard) {
428e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        if (clipboard.primaryClip == null) {
42990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            return;
43090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
431e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        final int N = clipboard.primaryClip.getItemCount();
43290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        for (int i=0; i<N; i++) {
433e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            revokeItemLocked(clipboard.primaryClip.getItemAt(i));
43490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
43590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
437