104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov/* 204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * Copyright (C) 2016 The Android Open Source Project 304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * 404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * you may not use this file except in compliance with the License. 604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * You may obtain a copy of the License at 704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * 804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * http://www.apache.org/licenses/LICENSE-2.0 904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * 1004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software 1104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS, 1204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * See the License for the specific language governing permissions and 1404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * limitations under the License. 1504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov */ 1604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 1704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovpackage android.util; 1804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 1904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovimport android.content.ComponentName; 2004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovimport android.content.Context; 2104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovimport android.content.Intent; 2204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovimport android.content.ServiceConnection; 2304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovimport android.os.Build; 2404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovimport android.os.IBinder; 2504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovimport android.os.RemoteException; 2604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovimport android.os.SystemClock; 2704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovimport android.support.test.InstrumentationRegistry; 2804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 2904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovimport java.io.Closeable; 3004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovimport java.io.IOException; 3104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovimport java.util.concurrent.TimeoutException; 3204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 3304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovfinal class RemoteIntArray implements ServiceConnection, Closeable { 3404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov private static final long BIND_REMOTE_SERVICE_TIMEOUT = 3504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov ("eng".equals(Build.TYPE)) ? 120000 : 10000; 3604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 3704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov private final Object mLock = new Object(); 3804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 3904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov private final Intent mIntent = new Intent(); 4004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 4104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov private android.util.IRemoteMemoryIntArray mRemoteInstance; 4204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 4374c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov public RemoteIntArray(int size) throws IOException, TimeoutException { 4404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov mIntent.setComponent(new ComponentName(InstrumentationRegistry.getContext(), 4504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov RemoteMemoryIntArrayService.class)); 4604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov synchronized (mLock) { 4704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov if (mRemoteInstance == null) { 4804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov bindLocked(); 4904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 5004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov try { 5174c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov mRemoteInstance.create(size); 5204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } catch (RemoteException e) { 5304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov throw new IOException(e); 5404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 5504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 5604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 5704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 5804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov public MemoryIntArray peekInstance() { 5904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov try { 6004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov return mRemoteInstance.peekInstance(); 6104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } catch (RemoteException e) { 6204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov throw new RuntimeException(e); 6304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 6404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 6504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 6604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov public boolean isWritable() { 6704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov try { 6804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov return mRemoteInstance.isWritable(); 6904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } catch (RemoteException e) { 7004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov throw new RuntimeException(e); 7104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 7204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 7304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 7404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov public int get(int index) throws IOException { 7504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov try { 7604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov return mRemoteInstance.get(index); 7704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } catch (RemoteException e) { 7804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov throw new IOException(e); 7904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 8004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 8104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 8204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov public void set(int index, int value) throws IOException { 8304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov try { 8404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov mRemoteInstance.set(index, value); 8504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } catch (RemoteException e) { 8604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov throw new IOException(e); 8704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 8804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 8904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 9004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov public int size() throws IOException { 9104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov try { 9204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov return mRemoteInstance.size(); 9304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } catch (RemoteException e) { 9404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov throw new IOException(e); 9504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 9604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 9704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 9804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov public void close() { 9904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov try { 10004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov mRemoteInstance.close(); 10104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } catch (RemoteException e) { 10204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov throw new RuntimeException(e); 10304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 10404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 10504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 10604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov public boolean isClosed() { 10704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov try { 10804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov return mRemoteInstance.isClosed(); 10904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } catch (RemoteException e) { 11004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov throw new RuntimeException(e); 11104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 11204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 11304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 11404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov private void bindLocked() throws TimeoutException { 11504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov if (mRemoteInstance != null) { 11604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov return; 11704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 11804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 11904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov InstrumentationRegistry.getContext().bindService(mIntent, this, Context.BIND_AUTO_CREATE); 12004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 12104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov final long startMillis = SystemClock.uptimeMillis(); 12204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov while (true) { 12304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov if (mRemoteInstance != null) { 12404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov break; 12504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 12604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; 12704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov final long remainingMillis = BIND_REMOTE_SERVICE_TIMEOUT - elapsedMillis; 12804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov if (remainingMillis <= 0) { 12904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov throw new TimeoutException("Cannot get spooler!"); 13004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 13104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov try { 13204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov mLock.wait(remainingMillis); 13304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } catch (InterruptedException ie) { 13404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov /* ignore */ 13504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 13604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 13704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 13804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov mLock.notifyAll(); 13904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 14004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 14104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov public void destroy() { 14204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov synchronized (mLock) { 14304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov if (mRemoteInstance == null) { 14404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov return; 14504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 14604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov mRemoteInstance = null; 14704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov InstrumentationRegistry.getContext().unbindService(this); 14804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 14904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 15004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 15174c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov public void accessLastElementInRemoteProcess(MemoryIntArray array) { 15274c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov try { 15374c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov mRemoteInstance.accessLastElementInRemoteProcess(array); 15474c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov } catch (RemoteException e) { 15574c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov throw new RuntimeException(e); 15674c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov } 15774c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov } 15874c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov 15904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov @Override 16004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov public void onServiceConnected(ComponentName name, IBinder service) { 16104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov synchronized (mLock) { 16204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov mRemoteInstance = android.util.IRemoteMemoryIntArray.Stub.asInterface(service); 16304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov mLock.notifyAll(); 16404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 16504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 16604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 16704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov @Override 16804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov public void onServiceDisconnected(ComponentName name) { 16904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov synchronized (mLock) { 17004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov mRemoteInstance = null; 17104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 17204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 17304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov}