Android Ashmem匿名共享内存 Java实例
2017-04-10 15:06
399 查看
packages/experimental/
知识点:
1、需要用反射来获取 MemoryFile.getFileDescriptor方法以及设置private成员变量;
2、AIDL的使用。
Ashmem/aidl/com/mycompany/ashmem/IMemoryService.aidl
// IMemoryService.aidl package com.mycompany.ashmem; import android.os.ParcelFileDescriptor; // Declare any non-default types here with import statements interface IMemoryService { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); ParcelFileDescriptor getFileDescriptor(); void setValue(int val); }
由Ashmem/aidl/com/mycompany/ashmem/IMemoryService.aidl编译出来的 IMemoryService.java文件
/* * This file is auto-generated. DO NOT MODIFY. * Original file: packages/experimental/Ashmem/aidl/com/mycompany/ashmem/IMemoryService.aidl */ package com.mycompany.ashmem; // Declare any non-default types here with import statements public interface IMemoryService extends android.os.IInterface { /** * Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.mycompany.ashmem.IMemoryService { private static final java.lang.String DESCRIPTOR = "com.mycompany.ashmem.IMemoryService"; /** * Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.mycompany.ashmem.IMemoryService interface, * generating a proxy if needed. */ public static com.mycompany.ashmem.IMemoryService asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.mycompany.ashmem.IMemoryService))) { return ((com.mycompany.ashmem.IMemoryService) iin); } return new com.mycompany.ashmem.IMemoryService.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_basicTypes: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); long _arg1; _arg1 = data.readLong(); boolean _arg2; _arg2 = (0 != data.readInt()); float _arg3; _arg3 = data.readFloat(); double _arg4; _arg4 = data.readDouble(); java.lang.String _arg5; _arg5 = data.readString(); this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5); reply.writeNoException(); return true; } case TRANSACTION_getFileDescriptor: { data.enforceInterface(DESCRIPTOR); android.os.ParcelFileDescriptor _result = this.getFileDescriptor(); reply.writeNoException(); if ((_result != null)) { reply.writeInt(1); _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { reply.writeInt(0); } return true; } case TRANSACTION_setValue: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); this.setValue(_arg0); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.mycompany.ashmem.IMemoryService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(anInt); _data.writeLong(aLong); _data.writeInt(((aBoolean) ? (1) : (0))); _data.writeFloat(aFloat); _data.writeDouble(aDouble); _data.writeString(aString); mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public android.os.ParcelFileDescriptor getFileDescriptor() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); android.os.ParcelFileDescriptor _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getFileDescriptor, _data, _reply, 0); _reply.readException(); if ((0 != _reply.readInt())) { _result = android.os.ParcelFileDescriptor.CREATOR.createFromParcel(_reply); } else { _result = null; } } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public void setValue(int val) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(val); mRemote.transact(Stub.TRANSACTION_setValue, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_getFileDescriptor = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); static final int TRANSACTION_setValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2); } /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException; public android.os.ParcelFileDescriptor getFileDescriptor() throws android.os.RemoteException; public void setValue(int val) throws android.os.RemoteException; }
Ashmem/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mycompany.ashmem" android:sharedUserId="android.uid.system"> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:supportsRtl="true"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="com.mycompany.ashmem.Server"> <intent-filter> <action android:name="com.mycompany.ashmem.Server"></action> </intent-filter> </service> </application> </manifest>
Ashmem/Android.mk
# Copyright (C) 2010 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_SRC_FILES += aidl/com/mycompany/ashmem/IMemoryService.aidl LOCAL_PACKAGE_NAME := Ashmem LOCAL_CERTIFICATE := platform include $(BUILD_PACKAGE)
Ashmem/res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.mycompany.ashmem.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/value" /> <EditText android:id="@+id/editText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:inputType="number" android:hint="@string/hint"/> <Button android:id="@+id/button_read" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/read" tools:layout_editor_absoluteX="48dp" tools:layout_editor_absoluteY="209dp" /> <Button android:id="@+id/button_write" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/write" tools:layout_editor_absoluteX="48dp" tools:layout_editor_absoluteY="274dp" /> <Button android:id="@+id/button_clear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/clear" tools:layout_editor_absoluteX="48dp" tools:layout_editor_absoluteY="333dp" /> </LinearLayout> Ashmem/res/values/strings.xml <resources> <string name="app_name">Ashmem</string> <string name="value" /> <string name="hint">Please input a value...</string> <string name="read">Read</string> <string name="write">write</string> <string name="clear">clear</string> </resources>
Ashmem
└── src
└── com
└── mycompany
└── ashmem
├── MainActivity.java
package com.mycompany.ashmem; import android.app.Activity; import android.content.Intent; import android.content.ComponentName; import android.os.MemoryFile; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import java.io.FileDescriptor; import java.io.IOException; import java.io.*; import java.lang.reflect.*; import android.os.ServiceManager; public class MainActivity extends Activity implements View.OnClickListener { private final static String TAG = "MainActivity"; IMemoryService memoryService = null; MemoryFile memoryFile = null; FileInputStream inputStream = null; private EditText valueText = null; private Button readButton = null; private Button writeButton = null; private Button clearButton = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); IMemoryService ms = getMemoryService(); if (ms == null) { Log.i(TAG, "start server"); Intent intents = new Intent(); intents.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intents.setClassName("com.mycompany.ashmem", "com.mycompany.ashmem.Server"); startService(intents); } else { Log.i(TAG, "Memory Service has started."); } valueText = (EditText) findViewById(R.id.editText); readButton = (Button) findViewById(R.id.button_read); writeButton = (Button) findViewById(R.id.button_write); clearButton = (Button) findViewById(R.id.button_clear); readButton.setOnClickListener(this); writeButton.setOnClickListener(this); clearButton.setOnClickListener(this); Log.i(TAG, "client activity cretaed."); } @Override public void onClick(View v) { int val = 0; String text = ""; switch (v.getId()) { case R.id.button_read: Log.i(TAG, "button read."); val = 0; MemoryFile mf = getMemoryFile(); if (mf != null) { try { byte[] buffer = new byte[4]; mf.readBytes(buffer, 0, 0, 4); val = (buffer[0] << 24) | ((buffer[1] & 0xFF) << 16) | ((buffer[2] & 0xFF) << 8) | (buffer[3] & 0xFF); Log.i(TAG, "read file " + val); } catch (IOException e) { Log.i(TAG, "Failed to read bytes from memory file."); e.printStackTrace(); } } else { Log.e(TAG, "MemoryFile is null"); } text = String.valueOf(val); valueText.setText(text); valueText.setSelection(valueText.getText().length()); break; case R.id.button_write: Log.i(TAG, "button write."); text = valueText.getText().toString(); if (text.equals("")) { Toast.makeText(this, "Please input a number!", Toast.LENGTH_SHORT).show(); break; } try { val = Integer.parseInt(text); } catch (NumberFormatException e) { Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show(); break; } IMemoryService ms = getMemoryService(); if (ms != null) { try { ms.setValue(val); } catch (RemoteException e) { Log.e(TAG, "Failed to set value to memory service."); e.printStackTrace(); } } else { Log.e(TAG, "Memory Service is null"); } break; case R.id.button_clear: text = ""; valueText.setText(text); break; } } private IMemoryService getMemoryService() { if (memoryService != null) { Log.i(TAG, "memory service aleady started."); return memoryService; } memoryService = IMemoryService.Stub.asInterface(ServiceManager.getService("AnonymousSharedMemory")); Log.i(TAG, memoryService != null ? "Succeed to get memory service." : "Failed to get memory service."); return memoryService; } /** * */ public void setField(String className, Object instance, String fieldName, Object value) { if (className == null || className.equals("")) { throw new IllegalArgumentException("className is null"); } if (fieldName == null || fieldName.equals("")) { throw new IllegalArgumentException("fieldName is null"); } try { Class<?> c = Class.forName(className); Field field = c.getDeclaredField(fieldName); field.setAccessible(true); field.set(instance, value); } catch (Exception e) { e.printStackTrace(); } } private MemoryFile getMemoryFile() { if (memoryFile != null) { return memoryFile; } IMemoryService ms = getMemoryService(); if (ms != null) { try { ParcelFileDescriptor pfd = ms.getFileDescriptor(); if (pfd == null) { Log.i(TAG, "Failed to get memory file descriptor."); return null; } FileDescriptor fd = pfd.getFileDescriptor(); if (fd == null) { Log.e(TAG, "Failed to get memory file descriptor."); return null; } int length = 4; memoryFile = new MemoryFile("r", length); memoryFile.close(); try { Method native_mmap = null; Method[] methods = MemoryFile.class.getDeclaredMethods(); for (int i = 0; methods != null && i < methods.length; i++) { if (methods[i].getName().equals("native_mmap")) { Log.i(TAG, "native_mmap finded."); native_mmap = methods[i]; setField("android.os.MemoryFile", memoryFile, "mFD", fd); setField("android.os.MemoryFile", memoryFile, "mLength", length); native_mmap.setAccessible(true); long address = (long) native_mmap.invoke(null, fd, length, 0x01 | 0x02); setField("android.os.MemoryFile", memoryFile, "mAddress", address); } } } catch (IllegalAccessException e) { Log.e(TAG, "IllegalAccessException:" + e.getMessage()); e.printStackTrace(); } catch (InvocationTargetException e) { Log.e(TAG, "InvocationTargetException:" + e.getMessage()); e.printStackTrace(); } return memoryFile; } catch (RemoteException e) { Log.e(TAG, "Failed to get file descriptor from memory service."); e.printStackTrace(); } catch (IOException e) { Log.e(TAG, "Failed to create memory file."); e.printStackTrace(); } } else { Log.e(TAG, "memory service is null"); } return memoryFile; } }
Ashmem
└── src
└── com
└── mycompany
└── ashmem
├── MemoryService.java
package com.mycompany.ashmem; import android.os.MemoryFile; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Log; import java.io.IOException; import java.io.*; import java.lang.reflect.*; /** * Created by Administrator on 2017/4/1. */ public class MemoryService extends IMemoryService.Stub { private final static String TAG = "MemoryService"; private MemoryFile file = null; public MemoryService() { Log.i(TAG, "MemoryService"); try { file = new MemoryFile("Ashmem", 4); setValue(0); } catch (IOException e) { Log.i(TAG, "Failed to create memory file."); e.printStackTrace(); } catch (RemoteException e) { Log.i(TAG, "Failed to setValue()."); e.printStackTrace(); } } @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public ParcelFileDescriptor getFileDescriptor() throws RemoteException { ParcelFileDescriptor pfd = null; try { Method method = MemoryFile.class.getDeclaredMethod("getFileDescriptor"); FileDescriptor fd = (FileDescriptor) method.invoke(file); pfd = ParcelFileDescriptor.dup(fd); // FileDescriptor fd = file.getFileDescriptor(); // pfd = ParcelFileDescriptor.dup(fd); Log.i(TAG, "getFileDescriptor:" + pfd); } catch (IOException e) { Log.e(TAG, "IOException:" + e.getMessage()); e.printStackTrace(); } catch (NoSuchMethodException e) { Log.e(TAG, "NoSuchMethodException:" + e.getMessage()); e.printStackTrace(); } catch (IllegalAccessException e) { Log.e(TAG, "IllegalAccessException:" + e.getMessage()); e.printStackTrace(); } catch (InvocationTargetException e) { Log.e(TAG, "InvocationTargetException:" + e.getMessage()); e.printStackTrace(); } return pfd; } @Override public void setValue(int val) throws RemoteException { if (file == null) { Log.e(TAG, "Memory file is null."); return; } Log.i(TAG, "setValue:" + val); byte[] buffer = new byte[4]; buffer[0] = (byte) ((val >>> 24) & 0xFF); buffer[1] = (byte) ((val >>> 16) & 0xFF); buffer[2] = (byte) ((val >>> 8) & 0xFF); buffer[3] = (byte) (val & 0xFF); try { file.writeBytes(buffer, 0, 0, 4); Log.i(TAG, "Set value " + val + " " + buffer[0] + buffer[1] + buffer[2] + buffer[3] + " to memory file."); } catch (IOException e) { Log.i(TAG, "Failed to write bytes to memory file."); e.printStackTrace(); } } }
Ashmem
└── src
└── com
└── mycompany
└── ashmem
├── Server.java
package com.mycompany.ashmem; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; import android.os.ServiceManager; import java.lang.reflect.Method; /** * Created by Administrator on 2017/4/5. */ public class Server extends Service { private final static String TAG = "Server"; private MemoryService memoryService = null; @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind"); return null; } @Override public void onCreate() { Log.i(TAG, "onCreate"); memoryService = new MemoryService(); try { ServiceManager.addService("AnonymousSharedMemory", memoryService); Log.i(TAG, "Succeed to add memory service."); } catch (RuntimeException e) { Log.e(TAG, "Failed to add Memory Service."); e.printStackTrace(); } } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); Log.i(TAG, "onStart"); } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, "onDestroy"); } }
相关文章推荐
- Android Ashmem匿名共享内存 C++实例
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析(上)
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析
- 匿名共享内存Ashmem实例--C++
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划 (三)
- android ashmem 匿名共享内存
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划 (五)
- Android系统匿名共享内存Ashmem
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析