/* * Copyright (C) 2016 Simon Fels * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * */ package org.anbox.appmgr; import android.os.ServiceManager; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; import android.util.Log; import android.content.Intent; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.ApplicationInfo; import android.net.Uri; import android.graphics.drawable.Drawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import java.util.List; import java.io.ByteArrayOutputStream; public final class PlatformService { private static final String TAG = "AnboxAppMgr"; private static final String SERVICE_NAME = "org.anbox.PlatformService"; private static final String DESCRIPTOR = "org.anbox.IPlatformService"; private static final int TRANSACTION_updateApplicationList = (IBinder.FIRST_CALL_TRANSACTION + 2); private IBinder mService = null; private PackageManager mPm = null; private void connectService() { if (mService != null) return; mService = ServiceManager.getService(SERVICE_NAME); } public PlatformService(Context context) { if (context != null) { mPm = context.getPackageManager(); } else { Log.w(TAG, "No context available"); } Log.i(TAG, "Connected to platform service"); } public void notifyPackageRemoved(String packageName) { connectService(); if (mService == null) return; Log.i(TAG, "Sending package removed notification to host service"); Parcel data = Parcel.obtain(); data.writeInterfaceToken(DESCRIPTOR); // No added or updated applications to report data.writeInt(0); // .. but a single removed application data.writeInt(1); data.writeString(packageName); Parcel reply = Parcel.obtain(); try { mService.transact(TRANSACTION_updateApplicationList, data, reply, 0); } catch (RemoteException ex) { Log.w(TAG, "Failed to send updatePackageList request to remote binder service: " + ex.getMessage()); } } public void sendApplicationListUpdate() { connectService(); if (mPm == null || mService == null) return; Parcel data = Parcel.obtain(); data.writeInterfaceToken(DESCRIPTOR); List apps = mPm.getInstalledApplications(0); data.writeInt(apps.size()); for (int n = 0; n < apps.size(); n++) { ApplicationInfo appInfo = apps.get(n); Intent launchIntent = mPm.getLaunchIntentForPackage(appInfo.packageName); if (launchIntent == null) continue; Drawable icon = null; try { icon = mPm.getApplicationIcon(appInfo.packageName); } catch (PackageManager.NameNotFoundException ex) { continue; } if (icon == null) continue; String name = appInfo.name; CharSequence label = appInfo.loadLabel(mPm); if (label != null) name = label.toString(); data.writeString(name); data.writeString(appInfo.packageName); data.writeString(launchIntent.getAction()); if (launchIntent.getData() != null) data.writeString(launchIntent.getData().toString()); else data.writeString(""); data.writeString(launchIntent.getType()); data.writeString(launchIntent.getComponent().getPackageName()); data.writeString(launchIntent.getComponent().getClassName()); data.writeInt(launchIntent.getCategories().size()); for (String category : launchIntent.getCategories()) data.writeString(category); Bitmap iconBitmap = drawableToBitmap(icon); ByteArrayOutputStream outStream = new ByteArrayOutputStream(); iconBitmap.compress(Bitmap.CompressFormat.PNG, 90, outStream); data.writeByteArray(outStream.toByteArray()); } // We don't have any removed applications to include in the update data.writeInt(0); Parcel reply = Parcel.obtain(); try { mService.transact(TRANSACTION_updateApplicationList, data, reply, 0); } catch (RemoteException ex) { Log.w(TAG, "Failed to send updatePackageList request to remote binder service: " + ex.getMessage()); } } private Bitmap drawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) return ((BitmapDrawable)drawable).getBitmap(); Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } }