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;
23e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasaniimport android.content.BroadcastReceiver;
241040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackbornimport android.content.ClipData;
251040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackbornimport android.content.ClipDescription;
26d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevotimport android.content.ContentProvider;
279f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.content.IClipboard;
289f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.content.IOnPrimaryClipChangedListener;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
3090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.content.Intent;
31e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasaniimport android.content.IntentFilter;
32ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tateimport android.content.pm.IPackageManager;
3390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.content.pm.PackageInfo;
3490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.content.pm.PackageManager;
35f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevotimport android.content.pm.UserInfo;
3690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.net.Uri;
3790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.os.Binder;
3890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.os.IBinder;
39f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevotimport android.os.IUserManager;
4090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.os.Parcel;
4190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.os.Process;
429f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.os.RemoteCallbackList;
439f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.os.RemoteException;
44f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevotimport android.os.ServiceManager;
45f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle;
46f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevotimport android.os.UserManager;
4790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackbornimport android.util.Slog;
48e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasaniimport android.util.SparseArray;
4990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
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 */
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ClipboardService extends IClipboard.Stub {
57e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
58e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    private static final String TAG = "ClipboardService";
59e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
6090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final Context mContext;
6190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final IActivityManager mAm;
62f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    private final IUserManager mUm;
6390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final PackageManager mPm;
64efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn    private final AppOpsManager mAppOps;
6590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final IBinder mPermissionOwner;
6690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
67efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn    private class ListenerInfo {
68efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn        final int mUid;
69efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn        final String mPackageName;
70efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn        ListenerInfo(int uid, String packageName) {
71efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            mUid = uid;
72efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            mPackageName = packageName;
73efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn        }
74efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn    }
75efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn
76e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    private class PerUserClipboard {
77e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        final int userId;
78e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
79e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        final RemoteCallbackList<IOnPrimaryClipChangedListener> primaryClipListeners
80e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                = new RemoteCallbackList<IOnPrimaryClipChangedListener>();
81e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
82e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        ClipData primaryClip;
83e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
84e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        final HashSet<String> activePermissionOwners
85e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                = new HashSet<String>();
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
87e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        PerUserClipboard(int userId) {
88e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            this.userId = userId;
89e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        }
90e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    }
9190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
92e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    private SparseArray<PerUserClipboard> mClipboards = new SparseArray<PerUserClipboard>();
9390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Instantiates the clipboard.
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    public ClipboardService(Context context) {
9890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        mContext = context;
9990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        mAm = ActivityManagerNative.getDefault();
10090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        mPm = context.getPackageManager();
101f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
102efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
10390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        IBinder permOwner = null;
10490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        try {
10590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            permOwner = mAm.newUriPermissionOwner("clipboard");
10690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } catch (RemoteException e) {
10790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            Slog.w("clipboard", "AM dead", e);
10890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
10990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        mPermissionOwner = permOwner;
110e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
111e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        // Remove the clipboard if a user is removed
112e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        IntentFilter userFilter = new IntentFilter();
113e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        userFilter.addAction(Intent.ACTION_USER_REMOVED);
114e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        mContext.registerReceiver(new BroadcastReceiver() {
115e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            @Override
116e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            public void onReceive(Context context, Intent intent) {
117e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                String action = intent.getAction();
118e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                if (Intent.ACTION_USER_REMOVED.equals(action)) {
1192a00329c6d55c6cd9166e01963d7410e95d80d21Amith Yamasani                    removeClipboard(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
120e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                }
121e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            }
122e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        }, userFilter);
12390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
12490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
12590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    @Override
12690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
12790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            throws RemoteException {
12890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        try {
12990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            return super.onTransact(code, data, reply, flags);
13090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } catch (RuntimeException e) {
131164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn            if (!(e instanceof SecurityException)) {
132164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn                Slog.wtf("clipboard", "Exception: ", e);
133164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn            }
13490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            throw e;
13590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
13690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
13790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
139e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    private PerUserClipboard getClipboard() {
140f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        return getClipboard(UserHandle.getCallingUserId());
141e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    }
142e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
143e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    private PerUserClipboard getClipboard(int userId) {
144e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        synchronized (mClipboards) {
145e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            PerUserClipboard puc = mClipboards.get(userId);
146e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            if (puc == null) {
147e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                puc = new PerUserClipboard(userId);
148e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                mClipboards.put(userId, puc);
149e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            }
150e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            return puc;
151e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        }
152e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    }
153e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
154e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    private void removeClipboard(int userId) {
155e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        synchronized (mClipboards) {
156e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            mClipboards.remove(userId);
157e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        }
158e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani    }
159e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani
160efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn    public void setPrimaryClip(ClipData clip, String callingPackage) {
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (this) {
1629f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            if (clip != null && clip.getItemCount() <= 0) {
1639f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                throw new IllegalArgumentException("No items");
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
165f0989840a00e53751241d0c97bf0e5a1866f6d4cDianne Hackborn            final int callingUid = Binder.getCallingUid();
166f0989840a00e53751241d0c97bf0e5a1866f6d4cDianne Hackborn            if (mAppOps.noteOp(AppOpsManager.OP_WRITE_CLIPBOARD, callingUid,
167efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                    callingPackage) != AppOpsManager.MODE_ALLOWED) {
168efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                return;
169efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            }
170f0989840a00e53751241d0c97bf0e5a1866f6d4cDianne Hackborn            checkDataOwnerLocked(clip, callingUid);
171f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            final int userId = UserHandle.getUserId(callingUid);
172f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            PerUserClipboard clipboard = getClipboard(userId);
173f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            revokeUris(clipboard);
174f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            setPrimaryClipInternal(clipboard, clip);
175f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            List<UserInfo> related = getRelatedProfiles(userId);
176f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            if (related != null) {
177f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                int size = related.size();
178f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                if (size > 1) { // Related profiles list include the current profile.
179f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    boolean canCopy = false;
180f0989840a00e53751241d0c97bf0e5a1866f6d4cDianne Hackborn                    try {
181f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                        canCopy = !mUm.getUserRestrictions(userId).getBoolean(
182f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                                UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
183f0989840a00e53751241d0c97bf0e5a1866f6d4cDianne Hackborn                    } catch (RemoteException e) {
184f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                        Slog.e(TAG, "Remote Exception calling UserManager: " + e);
185f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    }
186f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    // Copy clip data to related users if allowed. If disallowed, then remove
187f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    // primary clip in related users to prevent pasting stale content.
188f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    if (!canCopy) {
189f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                        clip = null;
190f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    } else {
191f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                        clip.fixUrisLight(userId);
192f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    }
193f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    for (int i = 0; i < size; i++) {
194f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                        int id = related.get(i).id;
195f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                        if (id != userId) {
196f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                            setPrimaryClipInternal(getClipboard(id), clip);
197f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                        }
198f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    }
199f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                }
200f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            }
201f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        }
202f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    }
203f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot
204f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    List<UserInfo> getRelatedProfiles(int userId) {
205f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        final List<UserInfo> related;
206f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        final long origId = Binder.clearCallingIdentity();
207f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        try {
208f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            related = mUm.getProfiles(userId, true);
209f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        } catch (RemoteException e) {
210f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            Slog.e(TAG, "Remote Exception calling UserManager: " + e);
211f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            return null;
212f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        } finally{
213f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            Binder.restoreCallingIdentity(origId);
214f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        }
215f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        return related;
216f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    }
217f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot
218f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    void setPrimaryClipInternal(PerUserClipboard clipboard, ClipData clip) {
219f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        clipboard.activePermissionOwners.clear();
220f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        if (clip == null && clipboard.primaryClip == null) {
221f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            return;
222f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        }
223f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        clipboard.primaryClip = clip;
224f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        final long ident = Binder.clearCallingIdentity();
225f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        final int n = clipboard.primaryClipListeners.beginBroadcast();
226f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        try {
227f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            for (int i = 0; i < n; i++) {
228f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                try {
229f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    ListenerInfo li = (ListenerInfo)
230f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                            clipboard.primaryClipListeners.getBroadcastCookie(i);
231f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    if (mAppOps.checkOpNoThrow(AppOpsManager.OP_READ_CLIPBOARD, li.mUid,
232f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                            li.mPackageName) == AppOpsManager.MODE_ALLOWED) {
233f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                        clipboard.primaryClipListeners.getBroadcastItem(i)
234f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                                .dispatchPrimaryClipChanged();
235efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                    }
236f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                } catch (RemoteException e) {
237f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    // The RemoteCallbackList will take care of removing
238f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    // the dead object for us.
2399f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                }
2409f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            }
241f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        } finally {
242f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            clipboard.primaryClipListeners.finishBroadcast();
243f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            Binder.restoreCallingIdentity(ident);
2449f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
2459f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    public ClipData getPrimaryClip(String pkg) {
2489f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        synchronized (this) {
249efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            if (mAppOps.noteOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
250efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                    pkg) != AppOpsManager.MODE_ALLOWED) {
251efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                return null;
252efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            }
25390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            addActiveOwnerLocked(Binder.getCallingUid(), pkg);
254e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            return getClipboard().primaryClip;
2559f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
2569f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
2579f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
258efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn    public ClipDescription getPrimaryClipDescription(String callingPackage) {
2591040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn        synchronized (this) {
260efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
261efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                    callingPackage) != AppOpsManager.MODE_ALLOWED) {
262efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                return null;
263efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            }
264e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            PerUserClipboard clipboard = getClipboard();
265e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            return clipboard.primaryClip != null ? clipboard.primaryClip.getDescription() : null;
2661040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn        }
2671040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn    }
2681040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn
269efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn    public boolean hasPrimaryClip(String callingPackage) {
2709f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        synchronized (this) {
271efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
272efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                    callingPackage) != AppOpsManager.MODE_ALLOWED) {
273efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                return false;
274efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            }
275e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            return getClipboard().primaryClip != null;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn    public void addPrimaryClipChangedListener(IOnPrimaryClipChangedListener listener,
280efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            String callingPackage) {
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (this) {
282efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            getClipboard().primaryClipListeners.register(listener,
283efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                    new ListenerInfo(Binder.getCallingUid(), callingPackage));
2849f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
2859f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
2869f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
2879f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    public void removePrimaryClipChangedListener(IOnPrimaryClipChangedListener listener) {
2889f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        synchronized (this) {
289e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            getClipboard().primaryClipListeners.unregister(listener);
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
293efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn    public boolean hasClipboardText(String callingPackage) {
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (this) {
295efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
296efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                    callingPackage) != AppOpsManager.MODE_ALLOWED) {
297efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn                return false;
298efcc1a23a1f731390ef8506b3536b9562d18ed78Dianne Hackborn            }
299e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            PerUserClipboard clipboard = getClipboard();
300e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            if (clipboard.primaryClip != null) {
301e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani                CharSequence text = clipboard.primaryClip.getItemAt(0).getText();
3029f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                return text != null && text.length() > 0;
3039f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            }
3049f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            return false;
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
30790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
30890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final void checkUriOwnerLocked(Uri uri, int uid) {
30990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (!"content".equals(uri.getScheme())) {
31090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            return;
31190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
31290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        long ident = Binder.clearCallingIdentity();
31390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        try {
31490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            // This will throw SecurityException for us.
315d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot            mAm.checkGrantUriPermission(uid, null, ContentProvider.getUriWithoutUserId(uri),
316f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    Intent.FLAG_GRANT_READ_URI_PERMISSION,
317f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(uid)));
31890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } catch (RemoteException e) {
31990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } finally {
32090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            Binder.restoreCallingIdentity(ident);
32190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
32290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
32390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
32490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final void checkItemOwnerLocked(ClipData.Item item, int uid) {
32590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (item.getUri() != null) {
32690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            checkUriOwnerLocked(item.getUri(), uid);
32790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
32890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        Intent intent = item.getIntent();
32990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (intent != null && intent.getData() != null) {
33090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            checkUriOwnerLocked(intent.getData(), uid);
33190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
33290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
33390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
33490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final void checkDataOwnerLocked(ClipData data, int uid) {
33590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        final int N = data.getItemCount();
33690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        for (int i=0; i<N; i++) {
337327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn            checkItemOwnerLocked(data.getItemAt(i), uid);
33890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
33990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
34090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
341f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    private final void grantUriLocked(Uri uri, String pkg, int userId) {
34290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        long ident = Binder.clearCallingIdentity();
34390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        try {
344f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            int sourceUserId = ContentProvider.getUserIdFromUri(uri, userId);
345f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            uri = ContentProvider.getUriWithoutUserId(uri);
346d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot            mAm.grantUriPermissionFromOwner(mPermissionOwner, Process.myUid(), pkg,
347f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId, userId);
34890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } catch (RemoteException e) {
34990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } finally {
35090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            Binder.restoreCallingIdentity(ident);
35190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
35290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
35390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
354f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    private final void grantItemLocked(ClipData.Item item, String pkg, int userId) {
35590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (item.getUri() != null) {
356f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            grantUriLocked(item.getUri(), pkg, userId);
35790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
35890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        Intent intent = item.getIntent();
35990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (intent != null && intent.getData() != null) {
360f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            grantUriLocked(intent.getData(), pkg, userId);
36190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
36290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
36390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
36490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final void addActiveOwnerLocked(int uid, String pkg) {
365ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate        final IPackageManager pm = AppGlobals.getPackageManager();
366ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate        final int targetUserHandle = UserHandle.getCallingUserId();
367ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate        final long oldIdentity = Binder.clearCallingIdentity();
36890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        try {
369ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate            PackageInfo pi = pm.getPackageInfo(pkg, 0, targetUserHandle);
370ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate            if (pi == null) {
371ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate                throw new IllegalArgumentException("Unknown package " + pkg);
372ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate            }
373f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn            if (!UserHandle.isSameApp(pi.applicationInfo.uid, uid)) {
37490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn                throw new SecurityException("Calling uid " + uid
37590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn                        + " does not own package " + pkg);
37690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            }
377ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate        } catch (RemoteException e) {
378ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate            // Can't happen; the package manager is in the same process
379ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate        } finally {
380ad9833a77ff4deb5352c67800c2ee62ed6e51356Christopher Tate            Binder.restoreCallingIdentity(oldIdentity);
38190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
382e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        PerUserClipboard clipboard = getClipboard();
383e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        if (clipboard.primaryClip != null && !clipboard.activePermissionOwners.contains(pkg)) {
384e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            final int N = clipboard.primaryClip.getItemCount();
38590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            for (int i=0; i<N; i++) {
386f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                grantItemLocked(clipboard.primaryClip.getItemAt(i), pkg, UserHandle.getUserId(uid));
38790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            }
388e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            clipboard.activePermissionOwners.add(pkg);
38990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
39090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
39190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
39290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final void revokeUriLocked(Uri uri) {
393f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot        int userId = ContentProvider.getUserIdFromUri(uri,
394f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                UserHandle.getUserId(Binder.getCallingUid()));
39590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        long ident = Binder.clearCallingIdentity();
39690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        try {
397f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            uri = ContentProvider.getUriWithoutUserId(uri);
398f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot            mAm.revokeUriPermissionFromOwner(mPermissionOwner, uri,
399d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot                    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
400f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot                    userId);
40190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } catch (RemoteException e) {
40290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        } finally {
40390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            Binder.restoreCallingIdentity(ident);
40490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
40590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
40690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
40790f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    private final void revokeItemLocked(ClipData.Item item) {
40890f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (item.getUri() != null) {
40990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            revokeUriLocked(item.getUri());
41090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
41190f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        Intent intent = item.getIntent();
41290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        if (intent != null && intent.getData() != null) {
41390f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            revokeUriLocked(intent.getData());
41490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
41590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
41690f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn
417f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot    private final void revokeUris(PerUserClipboard clipboard) {
418e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        if (clipboard.primaryClip == null) {
41990f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn            return;
42090f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
421e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani        final int N = clipboard.primaryClip.getItemCount();
42290f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        for (int i=0; i<N; i++) {
423e9e26cc727a1490db5eb0e572a40913f624529feAmith Yamasani            revokeItemLocked(clipboard.primaryClip.getItemAt(i));
42490f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn        }
42590f4aafa336d9f2f07281ead3c846d323a710015Dianne Hackborn    }
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
427