您的位置:首页 > 移动开发 > Android开发

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");
}
}






                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐