Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 04df96b1 authored by Chandan Nath's avatar Chandan Nath Committed by Android (Google) Code Review
Browse files

Merge "Add BackupEncryptionService which provides an IntermediateEncryptingTransport"

parents df535a3d 52eba65f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ android_app {
    name: "BackupEncryption",
    srcs: ["src/**/*.java"],
    libs: ["backup-encryption-protos"],
    static_libs: ["backuplib"],
    optimize: { enabled: false },
    platform_apis: true,
    certificate: "platform",
+10 −1
Original line number Diff line number Diff line
@@ -20,5 +20,14 @@
    package="com.android.server.backup.encryption"
    android:sharedUserId="android.uid.system" >

    <application android:allowBackup="false" />
    <application android:allowBackup="false" >
        <!-- This service does not need to be exported because it shares uid with the system server
        which is the only client. -->
        <service android:name=".BackupEncryptionService"
                 android:exported="false">
            <intent-filter>
                <action android:name="android.encryption.BACKUP_ENCRYPTION" />
            </intent-filter>
        </service>
    </application>
</manifest>
+63 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * 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.
 */

package com.android.server.backup.encryption;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import com.android.internal.backup.IBackupTransport;
import com.android.server.backup.encryption.transport.IntermediateEncryptingTransport;
import com.android.server.backup.encryption.transport.IntermediateEncryptingTransportManager;

/**
 * This service provides encryption of backup data. For an intent used to bind to this service, it
 * provides an {@link IntermediateEncryptingTransport} which is an implementation of {@link
 * IBackupTransport} that encrypts (or decrypts) the data when sending it (or receiving it) from the
 * real {@link IBackupTransport}.
 */
public class BackupEncryptionService extends Service {
    public static final String TAG = "BackupEncryption";
    private static IntermediateEncryptingTransportManager sTransportManager = null;

    @Override
    public void onCreate() {
        Log.i(TAG, "onCreate:" + this);
        if (sTransportManager == null) {
            Log.i(TAG, "Creating IntermediateEncryptingTransportManager");
            sTransportManager = new IntermediateEncryptingTransportManager(this);
        }
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy:" + this);
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO (b141536117): Check connection with TransportClient.connect and return null on fail.
        return sTransportManager.get(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        sTransportManager.cleanup(intent);
        return false;
    }
}
+64 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * 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.
 */

package com.android.server.backup.encryption.transport;

import android.os.RemoteException;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.backup.IBackupTransport;
import com.android.server.backup.transport.DelegatingTransport;
import com.android.server.backup.transport.TransportClient;

/**
 * This is an implementation of {@link IBackupTransport} that encrypts (or decrypts) the data when
 * sending it (or receiving it) from the {@link IBackupTransport} returned by {@link
 * TransportClient.connect(String)}.
 */
public class IntermediateEncryptingTransport extends DelegatingTransport {
    private final TransportClient mTransportClient;
    private final Object mConnectLock = new Object();
    private volatile IBackupTransport mRealTransport;

    @VisibleForTesting
    IntermediateEncryptingTransport(TransportClient transportClient) {
        mTransportClient = transportClient;
    }

    @Override
    protected IBackupTransport getDelegate() throws RemoteException {
        if (mRealTransport == null) {
            connect();
        }
        return mRealTransport;
    }

    private void connect() throws RemoteException {
        synchronized (mConnectLock) {
            if (mRealTransport == null) {
                mRealTransport = mTransportClient.connect("IntermediateEncryptingTransport");
                if (mRealTransport == null) {
                    throw new RemoteException("Could not connect: " + mTransportClient);
                }
            }
        }
    }

    @VisibleForTesting
    TransportClient getClient() {
        return mTransportClient;
    }
}
+97 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * 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.
 */

package com.android.server.backup.encryption.transport;

import static com.android.server.backup.encryption.BackupEncryptionService.TAG;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.backup.IBackupTransport;
import com.android.server.backup.transport.TransportClientManager;
import com.android.server.backup.transport.TransportStats;

import java.util.HashMap;
import java.util.Map;

/**
 * Handles creation and cleanup of {@link IntermediateEncryptingTransport} instances.
 */
public class IntermediateEncryptingTransportManager {
    private static final String CALLER = "IntermediateEncryptingTransportManager";
    private final TransportClientManager mTransportClientManager;
    private final Object mTransportsLock = new Object();
    private final Map<ComponentName, IntermediateEncryptingTransport> mTransports = new HashMap<>();

    @VisibleForTesting
    IntermediateEncryptingTransportManager(TransportClientManager transportClientManager) {
        mTransportClientManager = transportClientManager;
    }

    public IntermediateEncryptingTransportManager(Context context) {
        this(new TransportClientManager(UserHandle.myUserId(), context, new TransportStats()));
    }

    /**
     * Extract the {@link ComponentName} corresponding to the real {@link IBackupTransport}, and
     * provide a {@link IntermediateEncryptingTransport} which is an implementation of {@link
     * IBackupTransport} that encrypts (or decrypts) the data when sending it (or receiving it) from
     * the real {@link IBackupTransport}.
     * @param intent {@link Intent} created with a call to {@link
     * TransportClientManager.getEncryptingTransportIntent(ComponentName)}.
     * @return
     */
    public IntermediateEncryptingTransport get(Intent intent) {
        Intent transportIntent = TransportClientManager.getRealTransportIntent(intent);
        Log.i(TAG, "get: intent:" + intent + " transportIntent:" + transportIntent);
        synchronized (mTransportsLock) {
            return mTransports.computeIfAbsent(transportIntent.getComponent(),
                    c -> create(transportIntent));
        }
    }

    /**
     * Create an instance of {@link IntermediateEncryptingTransport}.
     */
    private IntermediateEncryptingTransport create(Intent realTransportIntent) {
        return new IntermediateEncryptingTransport(mTransportClientManager.getTransportClient(
                realTransportIntent.getComponent(), realTransportIntent.getExtras(), CALLER));
    }

    /**
     * Cleanup the {@link IntermediateEncryptingTransport} which was created by a call to
     * {@link #get(Intent)} with this {@link Intent}.
     */
    public void cleanup(Intent intent) {
        Intent transportIntent = TransportClientManager.getRealTransportIntent(intent);
        Log.i(TAG, "cleanup: intent:" + intent + " transportIntent:" + transportIntent);

        IntermediateEncryptingTransport transport;
        synchronized (mTransportsLock) {
            transport = mTransports.remove(transportIntent.getComponent());
        }
        if (transport != null) {
            mTransportClientManager.disposeOfTransportClient(transport.getClient(), CALLER);
        } else {
            Log.i(TAG, "Could not find IntermediateEncryptingTransport");
        }
    }
}
Loading