19f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn/**
29f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * Copyright (c) 2010, The Android Open Source Project
39f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn *
49f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
59f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * you may not use this file except in compliance with the License.
69f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * You may obtain a copy of the License at
79f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn *
89f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn *     http://www.apache.org/licenses/LICENSE-2.0
99f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn *
109f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * Unless required by applicable law or agreed to in writing, software
119f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
129f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * See the License for the specific language governing permissions and
149f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * limitations under the License.
159f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn */
169f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
179f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornpackage android.content;
189f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
199f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.content.Context;
209f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.os.Message;
219f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.os.RemoteException;
229f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.os.Handler;
239f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.os.IBinder;
249f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.os.ServiceManager;
259f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
269f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport java.util.ArrayList;
279f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
289f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn/**
299f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * Interface to the clipboard service, for placing and retrieving text in
309f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * the global clipboard.
319f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn *
329f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * <p>
339f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * You do not instantiate this class directly; instead, retrieve it through
349f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * {@link android.content.Context#getSystemService}.
359f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn *
3623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>
3723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * The ClipboardManager API itself is very simple: it consists of methods
3823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * to atomically get and set the current primary clipboard data.  That data
391040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * is expressed as a {@link ClipData} object, which defines the protocol
4023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * for data exchange between applications.
4123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn *
423aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <div class="special reference">
433aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <h3>Developer Guides</h3>
443aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <p>For more information about using the clipboard framework, read the
453aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy and Paste</a>
463aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * developer guide.</p>
473aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * </div>
483aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez *
499f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * @see android.content.Context#getSystemService
509f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn */
519f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornpublic class ClipboardManager extends android.text.ClipboardManager {
529f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    private final static Object sStaticLock = new Object();
539f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    private static IClipboard sService;
549f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
559f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    private final Context mContext;
569f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
579f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    private final ArrayList<OnPrimaryClipChangedListener> mPrimaryClipChangedListeners
589f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn             = new ArrayList<OnPrimaryClipChangedListener>();
599f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
609f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    private final IOnPrimaryClipChangedListener.Stub mPrimaryClipChangedServiceListener
619f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            = new IOnPrimaryClipChangedListener.Stub() {
629f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        public void dispatchPrimaryClipChanged() {
639f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            mHandler.sendEmptyMessage(MSG_REPORT_PRIMARY_CLIP_CHANGED);
649f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
659f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    };
669f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
679f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    static final int MSG_REPORT_PRIMARY_CLIP_CHANGED = 1;
689f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
699f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    private final Handler mHandler = new Handler() {
709f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        @Override
719f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        public void handleMessage(Message msg) {
729f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            switch (msg.what) {
739f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                case MSG_REPORT_PRIMARY_CLIP_CHANGED:
749f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                    reportPrimaryClipChanged();
759f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            }
769f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
779f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    };
789f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
79413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin    /**
80413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin     * Defines a listener callback that is invoked when the primary clip on the clipboard changes.
81413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin     * Objects that want to register a listener call
82413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin     * {@link android.content.ClipboardManager#addPrimaryClipChangedListener(OnPrimaryClipChangedListener)
83413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin     * addPrimaryClipChangedListener()} with an
84413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin     * object that implements OnPrimaryClipChangedListener.
85413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin     *
86413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin     */
879f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    public interface OnPrimaryClipChangedListener {
88413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin
89413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin        /**
90413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin         * Callback that is invoked by {@link android.content.ClipboardManager} when the primary
91413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin         * clip changes.
92413e9b3a5c1392ed8b80b66f00d9de5de0858b85Joe Malin         */
939f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        void onPrimaryClipChanged();
949f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
959f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
969f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    static private IClipboard getService() {
979f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        synchronized (sStaticLock) {
989f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            if (sService != null) {
999f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                return sService;
1009f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            }
1019f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            IBinder b = ServiceManager.getService("clipboard");
1029f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            sService = IClipboard.Stub.asInterface(b);
1039f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            return sService;
1049f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
1059f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
1069f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
1079f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    /** {@hide} */
1089f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    public ClipboardManager(Context context, Handler handler) {
1099f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        mContext = context;
1109f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
1119f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
1129f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    /**
1139f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     * Sets the current primary clip on the clipboard.  This is the clip that
1149f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     * is involved in normal cut and paste operations.
1159f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     *
1169f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     * @param clip The clipped data item to set.
1179f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     */
1181040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn    public void setPrimaryClip(ClipData clip) {
1199f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        try {
120a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey            if (clip != null) {
121a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey                clip.prepareToLeaveProcess();
122a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey            }
12395d785346b4dae808a2d8f77356175e55a572d96Dianne Hackborn            getService().setPrimaryClip(clip, mContext.getOpPackageName());
1249f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        } catch (RemoteException e) {
1259f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
1269f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
1279f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
1289f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    /**
1299f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     * Returns the current primary clip on the clipboard.
1309f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     */
1311040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn    public ClipData getPrimaryClip() {
1329f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        try {
13395d785346b4dae808a2d8f77356175e55a572d96Dianne Hackborn            return getService().getPrimaryClip(mContext.getOpPackageName());
1349f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        } catch (RemoteException e) {
1359f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            return null;
1369f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
1379f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
1389f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
1399f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    /**
1401040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn     * Returns a description of the current primary clip on the clipboard
1411040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn     * but not a copy of its data.
1421040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn     */
1431040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn    public ClipDescription getPrimaryClipDescription() {
1441040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn        try {
14595d785346b4dae808a2d8f77356175e55a572d96Dianne Hackborn            return getService().getPrimaryClipDescription(mContext.getOpPackageName());
1461040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn        } catch (RemoteException e) {
1471040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn            return null;
1481040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn        }
1491040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn    }
1501040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn
1511040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn    /**
1529f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     * Returns true if there is currently a primary clip on the clipboard.
1539f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     */
1549f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    public boolean hasPrimaryClip() {
1559f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        try {
15695d785346b4dae808a2d8f77356175e55a572d96Dianne Hackborn            return getService().hasPrimaryClip(mContext.getOpPackageName());
1579f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        } catch (RemoteException e) {
1589f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            return false;
1599f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
1609f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
1619f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
1629f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    public void addPrimaryClipChangedListener(OnPrimaryClipChangedListener what) {
1639f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        synchronized (mPrimaryClipChangedListeners) {
1649f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            if (mPrimaryClipChangedListeners.size() == 0) {
1659f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                try {
1669f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                    getService().addPrimaryClipChangedListener(
16795d785346b4dae808a2d8f77356175e55a572d96Dianne Hackborn                            mPrimaryClipChangedServiceListener, mContext.getOpPackageName());
1689f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                } catch (RemoteException e) {
1699f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                }
1709f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            }
1719f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            mPrimaryClipChangedListeners.add(what);
1729f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
1739f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
1749f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
1759f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    public void removePrimaryClipChangedListener(OnPrimaryClipChangedListener what) {
1769f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        synchronized (mPrimaryClipChangedListeners) {
1779f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            mPrimaryClipChangedListeners.remove(what);
1789f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            if (mPrimaryClipChangedListeners.size() == 0) {
1799f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                try {
1809f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                    getService().removePrimaryClipChangedListener(
1819f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                            mPrimaryClipChangedServiceListener);
1829f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                } catch (RemoteException e) {
1839f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                }
1849f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            }
1859f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
1869f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
1879f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
1889f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    /**
1899f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     * @deprecated Use {@link #getPrimaryClip()} instead.  This retrieves
1909f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     * the primary clip and tries to coerce it to a string.
1919f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     */
1929f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    public CharSequence getText() {
1931040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn        ClipData clip = getPrimaryClip();
1949f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        if (clip != null && clip.getItemCount() > 0) {
195327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn            return clip.getItemAt(0).coerceToText(mContext);
1969f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
1979f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        return null;
1989f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
1999f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
2009f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    /**
2011040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn     * @deprecated Use {@link #setPrimaryClip(ClipData)} instead.  This
2029f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     * creates a ClippedItem holding the given text and sets it as the
2039f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     * primary clip.  It has no label or icon.
2049f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     */
2059f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    public void setText(CharSequence text) {
206327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn        setPrimaryClip(ClipData.newPlainText(null, text));
2079f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
2089f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
2099f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    /**
21023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @deprecated Use {@link #hasPrimaryClip()} instead.
2119f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn     */
2129f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    public boolean hasText() {
2139f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        try {
21495d785346b4dae808a2d8f77356175e55a572d96Dianne Hackborn            return getService().hasClipboardText(mContext.getOpPackageName());
2159f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        } catch (RemoteException e) {
2169f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            return false;
2179f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
2189f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
2199f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
2209f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    void reportPrimaryClipChanged() {
2219f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        Object[] listeners;
2229f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
2239f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        synchronized (mPrimaryClipChangedListeners) {
2249f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            final int N = mPrimaryClipChangedListeners.size();
2259f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            if (N <= 0) {
2269f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn                return;
2279f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            }
2289f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            listeners = mPrimaryClipChangedListeners.toArray();
2299f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
2309f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn
2319f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        for (int i=0; i<listeners.length; i++) {
2329f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn            ((OnPrimaryClipChangedListener)listeners[i]).onPrimaryClipChanged();
2339f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn        }
2349f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn    }
2359f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn}
236